fmap与<$>

plx*_*plx 1 haskell

根据文档<$>是同义词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].


Wil*_*sem 6

这是由于运营商的优先权.如果我们查看源代码,我们会看到:

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)