<*>对于按照表示法实现的列表 - 这不是"作弊"吗?

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,ifconcatMap.来自Haskell报告:

[  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
Run Code Online (Sandbox Code Playgroud)

Monad []实例很容易定义concatMap,但concatMapGHC.List(现在可能已定义Data.Foldable)中定义.无论是GHC.ListData.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的应用.我认为以这种方式定义应用实例没有问题.

  • 我明白你的意思,但我的观点是关于“从头开始”构建应用程序。每次看到do-notation,我的第一个想法就是:“真的有必要吗?” (2认同)

Jon*_*ast 8

我错了,还是基于>> =这个含糖的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).


Ber*_*rgi 3

这个答案是对已经给出的答案的补充,并且仅关注问题的一部分:

\n\n
\n

据我了解,应该可以<*>仅使用 来实现列表fmap,就像应用程序 Maybe 的情况一样。如何?

\n
\n\n

您似乎参考了这个实现

\n\n
\n
instance Applicative Maybe where\n    pure = Just\n    Nothing  <*> _         = Nothing\n    (Just f) <*> something = fmap f something\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

嗯,是的,我们也可以对列表执行此操作 - 只使用fmap、模式匹配和构造函数:

\n\n
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\n
instance 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

\n