我正在haskellbook阅读关于申请的内容,并试图理解它。
在书中,作者提到:
所以,使用Applicative,我们的结构和功能都有一个Monoid 申请我们的价值观!
monoid如何连接到applicative?
答案 0 :(得分:8)
备注:我还没有拥有这本书,而且IIRC,至少有一位作者在SO上活跃,应该能够回答这个问题。话虽这么说,monoid(或者更确切地说是半群)背后的想法是你有办法从monoid 1 中的两个对象创建另一个对象:
mappend :: Monoid m => m -> m -> m
那么Applicative
如何成为幺半群?嗯,就其结构来说,它是一个幺半群,正如你的引述所说的那样。也就是说,我们从f something
开始,继续f anotherthing
,我们得到了,您已经猜到它是f resulthing
:
amappend :: f (a -> b) -> f a -> f b
在我们继续之前,在很短的时间内,让我们忘记f
有善意* -> *
。我们最终会得到什么?
amappend :: f -> f -> f
" monodial结构"部分。这就是Haskell中Applicative
和Functor
之间的区别,因为Functor
我们没有这个属性:
fmap :: (a -> b) -> f a -> f b
-- ^
-- no f here
如果我们尝试仅使用(+)
或仅使用fmap
的其他功能,那么我们也会遇到麻烦的原因:在单fmap
之后我们会卡住,除非我们能以某种方式在新结构中应用我们的新功能。这将我们带到你问题的第二部分:
因此,使用Applicative,我们有我们的价值观的功能应用程序!
功能应用程序是($)
。如果我们看一下<*>
,我们可以立即看到它们是相似的:
($) :: (a -> b) -> a -> b
(<*>) :: f (a -> b) -> f a -> f b
如果我们忘记了f
中的(<*>)
,我们最终会得到($)
。所以(<*>)
只是我们结构环境中的函数应用程序:
increase :: Int -> Int
increase x = x + 1
five :: Int
five = 5
increaseA :: Applicative f => f (Int -> Int)
increaseA = pure increase
fiveA :: Applicative f => f Int
fiveA = pure 5
normalIncrease = increase $ five
applicativeIncrease = increaseA <*> fiveA
我猜,作者的意思是&#34;功能应用&#34;。我们突然可以将那些隐藏在我们结构中的函数带到我们的结构中的其他值上。由于单一性质,我们留在那个结构中。
话虽如此,我个人永远不会称那个单调,因为<*>
不会对同一类型的两个参数进行操作,并且应用程序缺少空元素。
1 对于一个真正的半群/幺半群,操作应该是关联的,但这里并不重要
答案 1 :(得分:0)
尽管这个问题早已得到很好的回答,但我想补充一点。
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
在解释为什么我们需要一些Monoidal
类来解决有关Applicative
的问题之前,让我们首先看一下它的定律,并遵循该定律为我们提供一个类半身像:
f a
(x
)与f ((), a)
(unit ** x
)同构,这为我们提供了左身份。 (** unit) :: f a -> f ((), a)
,fmap snd :: f ((), a) -> f a
。f a
(x
)也是同构的f (a, ())
(x ** unit
),为我们提供了正确的身份。 (unit **) :: f a -> f (a, ())
,fmap fst :: f (a, ()) -> f a
。f ((a, b), c)
((x ** y) ** z
)与f (a, (b, c))
(x ** (y ** z)
)同构,这赋予了我们关联性。 fmap assoc :: f ((a, b), c) -> f (a, (b, c))
,fmap assoc' :: f (a, (b, c)) -> f ((a, b), c)
。您可能已经猜到,可以用Applicative
写下Monoidal
的方法,反之亦然:
unit = pure ()
f ** g = (,) <$> f <*> g = liftA2 (,) f g
pure x = const x <$> unit
f <*> g = uncurry id <$> (f ** g)
liftA2 f x y = uncurry f <$> (x ** y)
此外,可以证明Monoidal
和Applicative
律法在告诉我们同一件事。 I asked a question about this a while ago。