2013-03-12 2 views
10

Я пытаюсь обернуть голову вокруг оператора приложения функции ($) в Haskell.Попытка понять оператор приложения функции в Haskell

Я работаю с примерами в ЖЖ вас на Haskell, и я думал, что я понял, следующий пример:

Prelude> map ($ 3) [(+4), (*10), (^2), sqrt] 
[7.0,30.0,9.0,1.7320508075688772] 

Затем я попробовал следующий вариант, который также работал отлично:

Prelude> map ($ 3) [(+4), (*10), (\x -> x^2), sqrt] 
[7.0,30.0,9.0,1.7320508075688772] 

Наконец, я попытался модифицировать третью функцию в списке следующим образом, который генерирует сообщение об ошибке:

Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x), sqrt] 
<interactive>:53:38: 
    Ambiguous type variable `b0' in the constraints: 
     (Floating b0) 
     arising from a use of `sqrt' at <interactive>:53:38-41 
     (Integral b0) arising from a use of `^' at <interactive>:53:33 
     (Num b0) arising from the literal `3' at <interactive>:53:8 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the expression: sqrt 
    In the second argument of `map', namely 
     `[(+ 4), (* 10), (\ x -> 2^x), sqrt]' 
    In the expression: map ($ 3) [(+ 4), (* 10), (\ x -> 2^x), sqrt] 
Prelude> 

Кажется, если конечная sqrt функция как-то начать связан с предыдущим элементом списка, так как следующий вариант работает нормально:

Prelude> map ($ 3) [(+4), (*10), (\x -> 2^x)] 
[7,30,8] 

Может кто-нибудь просветить меня к тому, что здесь происходит?

+0

один урок, чтобы извлечь из этого, попробовав что-то в приглашении GHCi, проверьте его * тип *, с ** 'Прелюдия>: t it' **. «Это» - специальное слово, относящееся к предыдущему результату, и ': t' просит посмотреть тип. Вы могли видеть, что в вашем последнем примере нет десятичных точек в числах. Кроме того, после ввода ** ': s + t' ** в приглашении GHCi сообщит тип для каждого полученного результата. –

ответ

17

Тип используемого оператора возведения в степень является

(^) :: (Num a, Integral b) => a -> b -> a 

поэтому когда вы используете \x -> 2^x, вы получите Integral ограничение для 3. Но sqrt налагает ограничение Floating. Таким образом, тип 3 должен удовлетворять

3 :: (Integral t, Floating t) => t 

но нет ни одного случая, для обоих из списка типов по умолчанию, который Integer и Double, поэтому Нарушившие не удается, и вы остаетесь с переменным неоднозначным типом.

Когда вы были \x -> x^2, был только Num ограничение из первых функций, и Floating от sqrt, поэтому тип был дефолт Double.

Вы можете заставить его работать, если вы используете

(**) :: Floating a => a -> a -> a 

в качестве оператора возведения в степень, то тип может быть снова дефолте в Double.

+3

Тогда он мог исправить это, заменив (^) на (**). – zurgl

+0

Спасибо и Даниилу, и Зурглу - это многое проясняет. Исходя из Python, я все еще обволакивает последствия строгой проверки типов. –

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