2016-05-08 3 views
0

Замены скобок в этой функции:

isInteger x = x == fromInteger (round x) 

с оператором знак доллара:

isInteger x = x == fromInteger $ round x 

вызывает ошибку.

Каковы ограничения использования оператора $?

+0

Лучший вопрос SO не справляется с этой проблемой: http://stackoverflow.com/questions/940382/haskell-difference-between-dot-and-dollar-sign – Trajanson

+0

Это просто оператор инфикса с низким приоритетом. Вы получите сообщение об ошибке по той же причине: '3 * 5 + 7' означает' (3 * 5) + 7', а не '3 * (5 + 7)'. –

+0

@ DanielWagner вы можете определить «оператор инфикса», как вы понимаете этот термин? – Trajanson

ответ

6

$ имеет крайне низкий приоритет, ниже ==, ниже все. Попытка анализируется как

isInteger x = (x == fromInteger) $ (round x) 

, который он пытается применить Bool в качестве функции. Вы можете написать

isInteger x = x == (fromInteger $ round x) 

но это на самом деле не сохраняет никаких круглых скобок; это просто сдвигает их.


Если вы действительно хотите, чтобы избавиться от скобок (или, по крайней мере, на самом деле переместить их в сторону), вы можете воспользоваться тем, что (-> r) является аппликативным функтор, который вкратце означает, что f <*> g == \x -> f x (g x) , Замена f с (==) и g с fromInteger . round, вы получите

isInteger = (==) <*> fromInteger . round 

потому

x == fromInteger (round x) -> (==) x (fromInteger (round x)) 
          -> (==) x ((fromInteger . round) x) 
           ---- --------------------- 
           f x (   g   x) 
+1

Это хорошее разъяснение, объясняющее вам объяснение Хаскелла: «вы можете представить себе, что $ является эквивалентом написания открывающих круглых скобок, а затем писать закрытие в правой части выражения». – Trajanson

+5

Пока мы цитируем LYAH, я должен также упомянуть, что «[функции] редко используются с аппликативным стилем вне кода гольфа».Это умный, лаконичный и едва читаемый :) – chepner

+1

@chepner Это похоже на читаемость, если вы думаете о нем как о монаде «Читатель». – PyRulez

1

Это начало принятого ответа на вопрос, который вы связаны в комментариях:

$ для избежания скобок. Все, что появляется после , будет иметь приоритет над всем, что приходит раньше.

Принимая это во внимание, isInteger x = x == fromInteger $ round x становится isInteger x = (x == fromInteger) (round x), поэтому вы принимаете результат x == fromInteger (который типа Bool) и применить его к round x. Это явно не имеет смысла.

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