fmap与< $>

时间:2018-02-28 15:59:04

标签: haskell

根据文档<$>fmap的同义词,它们具有以下类型:

(<$>) :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> f a -> f b

所以在我看来,从上面的签名来看,他们以相同的顺序接受参数,唯一的区别是一个是中缀而另一个不是。我有两段代码,一段使用fmap,另一段使用<$>。为什么只有前者才能正确运行?

import Control.Applicative
main :: IO ()
main = do
  [x, y] <- map read . words <$> getLine
  putStrLn $ show (x + y)

这个不会编译:

import Control.Applicative
main :: IO ()
main = do
  [x, y] <- map read . fmap words getLine
  putStrLn $ show (x + y)

2 个答案:

答案 0 :(得分:11)

运算符的优先级表示为0到9之间的整数,而函数应用程序有效优先级为10(高于任何运算符)。

(.)具有非常高的优先级(9),而(<$>)具有较低的优先级(4),导致您的第一个表达式被解析为

((map read) . words) <$> getLine

,而您的第二个表达式被解析为

(map read) . (fmap words getLine) 

导致尝试使用IO [String]类型的函数撰写[String] -> [a]值。

答案 1 :(得分:6)

这是由运算符优先级引起的。如果我们查看源代码,我们会看到:

infixl 4 <$>
infixr 9  .

这意味着如果你写:

  map read . words  <$> getLine

Haskell将此视为:

(map read . words) <$> getLine

但如果你写:

 map read  .  fmap words getLine 

Haskell将此视为:

(map read) . (fmap words getLine)

所以fmap的论点不同。

如果我们添加括号,则两者将是等效的:

import Control.Applicative

main :: IO ()
main = do
  [x, y] <- map read . (words <$> getLine)
  putStrLn $ show (x + y)
相关问题