Ele*_*fee 20 parameters monads haskell functor applicative
我理解了<$>类型签名背后的原因,因为它只是一个中缀版本fmap,但是将它与>>=类型签名相比较,它对我来说没什么意义.
让我们首先确定我的意思.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(<$>) :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
查看类型签名,我们可以看到>>=左边是一个值,右边是一个函数,如果考虑它的链接属性,这很有意义:foo >>= bar >>= baz
这使我想知道,你为什么不<*>和<$>做到这一点?你不能写,foo <*> bar <*> baz因为它需要输出foo <*> bar是一个函数,而不是一个值.
我知道<**>并=<<存在这两个参数的顺序,允许我做类似的事情:
Just 4 <**> pure (+3) <**> pure (*2) >>= (\x -> Just (x-3))
Run Code Online (Sandbox Code Playgroud)
这本可以精美地减少到:
Just 4 <$$> (+3) <$$> (*2) >>= (\x -> Just (x-3))
Run Code Online (Sandbox Code Playgroud)
如果<$$>已经存在,或者如果参数顺序<$>,并<*>发生了逆转.
让我想知道为什么存在差异的另一件事是,它让新手更难以习惯和/或记住它是否是功能,或者首先是价值,而不必查阅它.
那么,为什么在案件<*>和<$>它的fn op val,但与>>=它的val op fn?
Don*_*art 22
不要让monad妨碍这里.考虑申请.
相比:
(<$>) :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
和
($) :: (a -> b) -> a -> b
Run Code Online (Sandbox Code Playgroud)
您可以看到常规应用程序与仿函数下的应用程序之间存在连接.
琐事:有建议使用括号来重载空格(应用程序),以便我们可以写:
(| f a1 .. an |)
Run Code Online (Sandbox Code Playgroud)
代替
pure f <*> a1 <*> .. <*> an
Run Code Online (Sandbox Code Playgroud)
Mat*_*hid 18
"为什么它按照这个顺序采取参数"的答案基本上是"因为".定义这些功能的人认为这是最好的方法.(在每种情况下,它可能不是同一个人.)但是,我将提供一些例子:
假设我们有某种解析monad.假设我们已经定义了
data Foobar = Foobar X Y Z
parseFoo :: Parser X
parseBar :: Parser Y
parseBaz :: Parser Z
Run Code Online (Sandbox Code Playgroud)
然后我们可以写
parseFoobar :: Parser Foobar
parseFoobar = do
foo <- parseFoo
bar <- parseBar
baz <- parseBaz
return (Foobar foo bar baz)
Run Code Online (Sandbox Code Playgroud)
或者,明确地,
parseFoobar =
parseFoo >>= \ foo ->
parseBar >>= \ bar ->
parseBaz >>= \ baz ->
return (Foobar foo bar baz)
Run Code Online (Sandbox Code Playgroud)
现在让我们写一下应用风格:
parseFoobar = return Foobar <*> parseFoo <*> parseBar <*> parseBaz
Run Code Online (Sandbox Code Playgroud)
或者,或者,
parseFoobar = Foobar <$> parseFoo <*> parseBar <*> parseBaz
Run Code Online (Sandbox Code Playgroud)
如果我们假设<**> = flip <*>存在(并且具有正确的关联性),那么我们就有了
parseFoobar = parseBaz <**> parseBar <**> parseFoo <**> return Foobar
Run Code Online (Sandbox Code Playgroud)
这看起来很奇怪.最后的函数和反向的参数?你为什么要这样写呢?(请注意,任何效果也是相反的顺序.)
在monadic版本中,效果从上到下发生.在应用版本中,效果从左到右发生.这似乎是"自然的".