Mar*_*lli 9 haskell list applicative
根据'Learn you a Haskell',<*>
for list 的实现是:
fs <*> xs = [f x | f <- fs, x <- xs]
Run Code Online (Sandbox Code Playgroud)
我错了,还是基于这个加糖的monadic代码>>=
?
据我了解,应该可以实现<*>仅使用fmap
,因为应用程序可能就是这种情况.
如何<*>
仅使用列表实现列表fmap
?(可能没有连接东西?)
顺便说一句,几页后,我看到关于执行同一个问题<*>
的应用性IO
.
Cir*_*dec 16
不,这不是基于糖的monadic代码>>=
.如果是,则定义>>=
的Monad []
实例将是圆形的.
instance Monad [] where
{-# INLINE (>>=) #-}
xs >>= f = [y | x <- xs, y <- f x]
...
Run Code Online (Sandbox Code Playgroud)
该列表内涵是语法糖let
,if
和concatMap
.来自Haskell报告:
Run Code Online (Sandbox Code Playgroud)[ e | b, Q ] = if b then [ e | Q ] else [] [ e | let decls, Q ] = let decls in [ e | Q ] [ e | p <- l, Q ] = let ok p = [ e | Q ] ok _ = [] in concatMap ok l
该Monad []
实例很容易定义concatMap
,但concatMap
在GHC.List
(现在可能已定义Data.Foldable
)中定义.无论是GHC.List
也Data.Foldable
被导入GHC.Base
,所以定义Monad
为列表实例GHC.Base
来讲concatMap
是不可能的:
instance Monad [] where
(>>=) = flip concatMap -- concatMap isn't imported
Run Code Online (Sandbox Code Playgroud)
根据列表理解来定义这些实例需要导入包含concatMap
重用它的模块定义>>=
.
在GHC中,列表推导有两种实现方式.一个用它来重写它们GHC.Base
build
并且foldr
类似于Data.Foldable
concatMap
.另一个实现生成递归函数来代替concatMap
Wadler所描述的.
bhe*_*ilr 10
Applicative
我见过很多情况下,实例都是由monadic函数满足的
instance Applicative MyMonadThatIsAlreadyDefined where
pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)
此外,<*>
不能仅使用fmap
,至少不一般.这就是重点<*>
.试着写<*>
一下fmap
,如果你管理它,我会非常惊讶(以一种表现良好并符合适用法律的方式).请记住链是
Functor > Applicative > Monad
Run Code Online (Sandbox Code Playgroud)
哪里>
可以被认为是超集.这就是说所有仿函数的集合包含所有应用程序的集合,其中包含所有monad的集合.如果你有一个monad,那么你拥有将它用作应用程序和仿函数所需的所有工具.有些类型是functorial但不适用,类型是非monadic的应用.我认为以这种方式定义应用实例没有问题.
我错了,还是基于>> =这个含糖的monadic代码?
我不知道是否>>=
实际上用于去糖列表理解(但请参阅Cirdec的答案,证明它不是),但实际上根据其定义是完全合法<*>
的>>=
.在数学术语中,每个Monad
实例都会引发一个唯一的对应Applicative
实例
instance Applicative F where
pure = return
af <*> ax = af >>= \ f -> ax >>= \ x -> return (f x)
Run Code Online (Sandbox Code Playgroud)
Applicative
每当F
有一个守法的例子时,这是一个守法的Monad
例子.
如果您熟悉它,可以从数学中进行类比:
类似地,对于每个monad结构,存在兼容的应用结构,并且对于每个应用结构,存在兼容的fmap
(fmap f ax = pure f <*> ax
),但是相反的含义不成立.
据我所知,应该可以仅使用fmap实现<*>,因为应用的是Maybe的情况.
我不明白你的意思. fmap
肯定不足以定义<*>
,或者每Functor
一个都是Applicative
(好吧,一个Apply
).
这个答案是对已经给出的答案的补充,并且仅关注问题的一部分:
\n\n\n\n\n据我了解,应该可以
\n<*>
仅使用 来实现列表fmap
,就像应用程序 Maybe 的情况一样。如何?
您似乎参考了这个实现:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\ninstance Applicative Maybe where\n pure = Just\n Nothing <*> _ = Nothing\n (Just f) <*> something = fmap f something\n
嗯,是的,我们也可以对列表执行此操作 - 只使用fmap
、模式匹配和构造函数:
instance Applicative [] where\n pure = []\n [] <*> _ = []\n (f:fs) <*> something = fmap f something ++ (fs <*> something)\n where\n [] ++ yy = ys\n (x:xs) ++ ys = x : (xs++ys)\n
Run Code Online (Sandbox Code Playgroud)\n\n不可否认,这确实需要某种连接,因为列表是比 Maybe 更复杂的类型。列表还有其他可能的应用实例,需要比这种“一切都包含一切”行为更少的代码,但这些实例与默认 monad 实例不兼容(这是普遍的期望)。
\n\n当然,单子表示法确实极大地简化了这一点:
\n\ninstance Monad m => Applicative m where\n pure = return\n mf <*> something = mf >>= (\\f -> fmap f something) -- shorter: (`fmap` something)\n
Run Code Online (Sandbox Code Playgroud)\n\n\xe2\x80\xa6 适用于Maybe
和[]
as m
。