根据文档<$>是同义词fmap,它们具有以下类型:
(<$>) :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
因此,在上面的签名中,我认为他们以相同的顺序接受参数,唯一的区别是一个是中缀而另一个不是.我有两段代码,一个使用fmap,另一个使用<$>.为什么只有前者运行正常?
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . words <$> getLine
putStrLn $ show (x + y)
Run Code Online (Sandbox Code Playgroud)
这个不会编译:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . fmap words getLine
putStrLn $ show (x + y)
Run Code Online (Sandbox Code Playgroud)
che*_*ner 11
运算符的优先级表示为0到9之间的整数,而函数应用程序有效地优先于10(高于任何运算符).
(.)具有非常高的优先级(9),而(<$>)优先级较低(4),导致您的第一个表达式被解析为
((map read) . words) <$> getLine
Run Code Online (Sandbox Code Playgroud)
而你的第二个表达式被解析为
(map read) . (fmap words getLine)
Run Code Online (Sandbox Code Playgroud)
导致尝试IO [String]使用类型函数组合值[String] -> [a].
这是由于运营商的优先权.如果我们查看源代码,我们会看到:
infixl 4 <$>
infixr 9 .Run Code Online (Sandbox Code Playgroud)
这意味着如果你写:
map read . words <$> getLine
Run Code Online (Sandbox Code Playgroud)
Haskell将此视为:
(map read . words) <$> getLine
Run Code Online (Sandbox Code Playgroud)
但如果你写:
map read . fmap words getLine
Run Code Online (Sandbox Code Playgroud)
Haskell将此视为:
(map read) . (fmap words getLine)
Run Code Online (Sandbox Code Playgroud)
所以论证fmap是不同的.
但是,如果我们添加括号,则两者将是等效的:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . (words <$> getLine)
putStrLn $ show (x + y)Run Code Online (Sandbox Code Playgroud)