Подтвердить что ты не робот

Совпадение шаблонов Haskell

Чтобы попасть в путь Haskell, я выбрал книгу одним из ее создателей Худаком. Итак, я прохожу через нежное введение в Haskell.

Я застрял в попытке понять следующее утверждение:

С технической точки зрения, формальные параметры также являются шаблонами, но они никогда не перестают соответствовать значению.

Из моего небольшого, но относительно большого привыкания с такими языками, как C (или широко говоря, как нефункциональные языки), я мог бы сформировать, что формальные параметры являются аргументами в определении функции. Итак, предположим, что в C была функция, подобная приведенной ниже:

int func_add(int a, int d) 

тогда передача значения какой-либо другой типа, такой как строка, будет ошибкой при сопоставлении с образцом, если я прав. Поэтому вызов func_add как func_add("trs", 5) является случаем несоответствия шаблона.

С большой возможностью неправильного понимания или интерпретации подобная ситуация может очень хорошо проявиться и в Haskell, когда часть кода вызывает функцию, передавая аргументы разных типов.

Итак, почему говорится, что формальные параметры Haskell являются неопровержимым сопоставлением шаблонов?

4b9b3361

Ответ 1

Нет, передача значения какого-либо другого типа не является ошибкой в ​​сопоставлении шаблонов. Это ошибка типа, и код даже не компилируется. Формальные параметры - неопровержимые шаблоны для хорошо типизированной программы, которая является единственным видом программы, которую позволяет компилятор.

Ответ 2

То, что вы описываете, не шаблон, это тип. Haskell также имеет типы, и они разрешаются во время компиляции. Каждый раз может быть несколько шаблонов. Например, список определяется как:

data Color = Red | Green | Blue | Other String

Теперь мы можем определить функцию foo:

foo :: Color -> String
foo Red = "Red"
foo Green = "Green"
foo Blue = "Blue"
foo (Other s) = s

Элементы жирного шрифта - это все шаблоны. Но они не являются неопровержимыми: первый проверяет, была ли задана функция a Red, вторая ли мы дали ей Green, третье, если значение Blue, и, наконец, у нас есть шаблон (Other s), который будет соответствовать всем шаблонам Other (независимо от того, что такое значение s), так как s - это переменная, а переменная - неопровержимый шаблон: мы не выполняем никаких проверок на значение строка.

Помните, что эти проверки выполняются во время выполнения: если бы мы вышли foo "Red", мы получим ошибку типа во время компиляции, так как компилятор Haskell знает, что foo имеет тип Color -> String.

Если бы мы написали:

foo :: Color -> String
foo c = "Some color"
foo Red = "Red"

c является неопровержимым шаблоном: он будет соответствовать любому объекту Color, поэтому вторая строка foo Red никогда не будет соответствовать, поэтому c является неопровержимым шаблоном.

Ответ 3

В Haskell вы можете определять типы различными способами. Один из них - ввести тип суммы, например:

data FooBar = Foo Int | Bar Bool

Вы можете попытаться написать такую ​​функцию, используя сопоставление с образцом:

myFunction (Foo x) = x

Это, однако, будет частично подобранной функцией, и если вы попытаетесь вызвать ее с помощью myFunction (Bar False), вы получите исключение.

С другой стороны, вы можете также определить типы сумм для одного случая, например:

data MyInt = MyInt Int

Здесь вы можете написать такую ​​функцию:

myFunction' (MyInt x) = x

Здесь вы по-прежнему используете сопоставление с образцом, но поскольку есть только один случай, это полное совпадение. Если код вызова компилируется, совпадение не может потерпеть неудачу.

Вышеупомянутый MyInt на самом деле является только оберткой вокруг Int, поэтому вы можете сказать, что если вы напишете функцию, которая принимает Int, например, это тот же тип соответствия шаблонов:

myFunction'' :: Int -> Int
myFunction'' x = x + 42

Пока Int не имеет конструктора значений, который можно использовать для сопоставления шаблонов, x - это шаблон, который всегда соответствует значению Int. Поэтому вы можете сказать, что аргумент функции - это совпадение, которое всегда выполняется успешно.