2013-07-22 2 views
4

Мой вопрос - о том, как аналитически работать с сигнатурами типа Haskell. Для того, чтобы сделать бетон, я смотрю на функции «исправления»:Упростить подписи типа Haskell

fix :: (a -> a) -> a 

и немного выдуманные функции, которую я написал, чтобы сделать Пеано-иш дополнения:

add = \rec a b -> if a == 0 then b else rec (a-1) (b+1) 

Когда я анализирую типы, я получу ожидаемый тип для fix add:

fix add :: Integer -> Integer -> Integer 

И это, кажется, работает, как я ожидал:

> (fix add) 1 1 
2 

Как я могу работать с типом сигнатур для fix и для add, чтобы показать, что у fix add есть подпись подписи? Что такое «алгебраический», если это даже правильное слово, правила работы с типом подписей? Как я могу «показать свою работу»?

ответ

8

ghci говорит нам

add :: Num a => (a -> a -> a) -> a -> a -> a

по модулю некоторые шумы, так как класс типов второй аргумент add требует Eq экземпляра (вы проверяете его на равенство с 0)

Когда мы применяем fix к add, подпись для fix будет

fix :: ((a -> a -> a) -> (a -> a -> a)) -> (a -> a -> a)

Помните, что a s в fix :: (a -> a) -> a может иметь любой типа. В этом случае они имеют тип (a -> a -> a)

Таким образом, fix add :: Num a => a -> a -> a, что является правильным выбором для добавления двух a.

Вы можете работать с сигнатурами типа Haskell в очень алгебраической форме, переменная подстановка работает так же, как вы ожидали. Фактически, theres прямой translation между типами и алгеброй.

+0

Спасибо! Я работал так же (что 'a' в' fix' должно быть '(a -> a -> a)'). Но разве еще не шаг? Есть ли промежуток между '((a -> a -> a) -> (a -> a -> a)) -> (a -> a -> a)' и 'a -> a -> a' ? – Chris

+0

Да, вы частично применяете 'fix' для' add'. Полученная частично примененная функция имеет тип 'a -> a -> a' – cdk

+3

@ twopoint718 Применение' fix' к 'add' удаляет' ((a -> a -> a) -> (a -> a -> a)) 'из типа' fix'. –

Смежные вопросы