0

У меня возникли проблемы с пониманием аргументации подписи типов в Haskell.Право-ассоциативность в типах сигнатур функций

1) как -> называется правым ассоциативным, означает ли это, что его можно понимать так же, как, например, 4^(2^(3^2))?

2) с использованием типа подписи простой функции так, чтобы выразить свои сомнения (объяснить, как я это понимаю, я буду использовать a, b, c вместо Num a => a «с или Int» ы):

myAdd :: a -> b -> c 
myAdd x y = x+y 

это означает, что функция принимает параметр a и возвращает функцию, которая принимает b и, наконец, возвращается c

Но это может быть переписано как:

myAdd :: (a->(b->c)) 

Поскольку большая часть учебного материала утверждает, что c в нашем примере является результатом функции myAdd, поэтому в зависимости от использования скобок это означает, что первая «операция» является b->c? Как вывести из этого типа подпись порядок выполненных операций?

3) Я была поставлена ​​задача реализовать

map f xs 

использованием foldr, (.) и (:) в результате которого:

map f xs = foldr ((:) . f) [] xs 

У меня нет проблем с пониманием выработок вышеуказанных функций , но здесь мы снова приходим - подписи типа. Если мы предположим, что имена унифицированы, поэтому тип a представляет один и тот же тип во всех контрактах, кажется, что c и d могут быть выражены в терминах a и b. В математике подобная задача, вероятно, была бы довольно простой, но как мне подойти к ней в Haskell?

map :: (a -> b) -> [a] -> [b] 
foldr :: (a -> c -> c) -> c -> [a] -> c 
(:) :: b -> ([b] -> [b]) 
(.) :: (b -> d) -> (a -> b) -> a -> d 
+3

Пожалуйста, сосредоточьте свой вопрос на одном должном образом ответственном аспекте. – leftaroundabout

+0

Операция, участвующая в части 1, создает тип функции. Тип функции, созданный «первым», - 'b -> c'. Затем он объединяется в более крупный тип функции 'a -> (b -> c)'. Обратите внимание, что все это находится на уровне типов, а не на уровне значений. '->' - это что-то, что принимает два типа и возвращает вам тип: тип функций от левого типа до нужного типа. Чтобы сделать что-то более конкретным, если вы даете '->' типы 'Char' и' Int', он возвращает вам тип функций от 'Char' до' Int'. –

ответ

5

Использование обозначений в

myAdd :: a -> b -> c 
myAdd x y = x+y 

вы правильно интерпретировать тип, как a -> (b->c) но вы продолжаете утверждать, что вычисление в b -> c как-то сделать в первую очередь.

Когда оценивается что-то вроде myAdd 2 10, функция оценки слева направо.

1) Оценка 1 myAdd 2. Результатом этой оценки является функция, которая отправляет заданное число y в 2 + y.В сущности, определение myAdd такого же, как

myAdd x = \y -> x+y 

2) Эта последняя функция затем применяется к аргументу 10 с получением 2 + 10 = 12

Таким образом, правильная ассоциативности -> в выражении в типа не соответствует праву на левый порядок вычислений в оценке функции . Фактически, оценка функции лево-ассоциативная: myAdd 2 10 - это то же самое, что и (myAdd 2) 10.

+0

Я понимаю лево-ассоциативность оценки функции, но не правая ассоциативность '->' в выражении типа. –

+5

Выражения типа говорят, что что-то * есть * - они не определяют порядок вычислений. 'a -> (b -> c)' говорит, что элемент типа 'a' сопоставляет то, что' is' является функцией, которая отправляет элементы типа 'b' в элементы типа' c'. Подумайте об этом как о логической группировке составных частей, а не о временной группировке вычислений. –