2013-12-15 3 views
1

У меня есть функция g1 = flip map . (flip take $ iterate (+1) 1) Я задаюсь вопросом, почему я не могу писатьприоритет оператора в Haskell

g1 = flip map . $ flip take $ iterate (+1) 1? Я знаю, что $ имеет самый низкий приоритет, но не понимаю, почему мы можем иметь $ в flip take $ iterate (+1) 1, но не в g1 после точки

ответ

3

Обратите внимание, что вторая форма приводит к ошибке синтаксического анализа, а не ошибка типа. У вас просто не может быть двух операторов бок о бок. Когда вы помещаете выражение между . и $, , то приоритеты оператора вступают в игру. Так как . имеет более высокий приоритет, выражение между . и $ становится правильным операндом ., а результат оператора точки становится левым операндом доллара. Если вы должны были отменить свои приоритеты (или написать код, предположив, что они были), вы получите ошибку типа (если типы не совпадают в любом случае).

Вы можете написать что-то вроде второй формы с помощью секции оператора:

g1 = (flip map .) $ flip take $ iterate (+1) 1 

Но я бы сказал, что наиболее читаемыми точка свободного обозначения

g1 = flip map . flip take (iterate (+1) 1) 

И на самом деле iterate (+1) 1 может быть сокращен :

g1 = flip map . flip take [1..] 

Далее, небольшое обессоливание помогает нам избавиться от flip take:

g1 = flip map . enumFromTo 1 
0

Давайте еще более простой пример:

Prelude> :t id . (id) 
id . (id) :: c -> c 
Prelude> :t id . $ id 

<interactive>:1:6: parse error on input `$' 
Prelude> :t (id .) $ id 
(id .) $ id :: c -> c 

Оператор $ имеет очень низкий приоритет, поэтому она оценивается в прошлом, и принимает функцию в качестве левого аргумента:

Prelude> :i ($) 
($) :: (a -> b) -> a -> b  -- Defined in `GHC.Base' 
infixr 0 $ 

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

Prelude> :t id . 

<interactive>:1:5: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> :t (id .) 
(id .) :: (a -> c) -> a -> c 
Prelude> :t flip take 
flip take :: [a] -> Int -> [a] 
Prelude> :t flip map . 

<interactive>:1:11: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> 

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

Prelude> :t + 

<interactive>:1:1: parse error on input `+' 
Prelude> :t (+) 
(+) :: Num a => a -> a -> a 
Prelude> :t 1+ 

<interactive>:1:3: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> :t (1+) 
(1+) :: Num a => a -> a 

Заключение: Вы просто не можете иметь два оператора непосредственно бок о бок.

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