根据文档<$>
是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)
答案 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)