根据“了解你一个Haskell”,列表<*>
的实现是:
fs <*> xs = [f x | f <- fs, x <- xs]
我错了,或者是基于>>=
据我了解,应该可以实现&lt; *&gt;仅使用fmap
,因为适用的是Maybe。
如何仅使用<*>
来实现列表的fmap
? (可能没有连接东西?)
顺便说一句,几页之后,我发现有关应用<*>
IO
的实施方面存在同样的问题。
答案 0 :(得分:16)
不,这不是基于>>=
的含糖单子代码。如果是,则Monad []
实例中的definition of >>=
将为圆形。
instance Monad [] where
{-# INLINE (>>=) #-}
xs >>= f = [y | x <- xs, y <- f x]
...
列表推导是let
,if
和concatMap
的语法糖。来自Haskell Report:
[ 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
实例是不可能的:< / p>
instance Monad [] where
(>>=) = flip concatMap -- concatMap isn't imported
根据列表理解来定义这些实例需要导入包含concatMap
的模块以重用它来定义>>=
。
在GHC中有两个implementations of list comprehensions。一个用GHC.Base
build
和foldr
重写它们,类似于Data.Foldable
concatMap
。另一个实现生成递归函数来代替concatMap
as described by Wadler。
答案 1 :(得分:10)
很多情况下Applicative
实例满足monadic函数,我见过
instance Applicative MyMonadThatIsAlreadyDefined where
pure = return
(<*>) = ap
此外,<*>
无法仅使用fmap
编写,至少一般不会。这就是<*>
的要点。尝试用<*>
来表达fmap
,如果你管理它,我将会非常惊讶(以一种表现良好并符合适用法律的方式)。请记住链是
Functor > Applicative > Monad
>
可以被认为是超集。这就是说所有仿函数的集合包含所有应用程序的集合,其中包含所有monad的集合。如果你有一个monad,那么你拥有将它用作应用程序和仿函数所需的所有工具。有些类型是functorial但不适用,类型是非monadic的应用。我认为以这种方式定义应用实例没有问题。
答案 2 :(得分:8)
我错了,或者这是基于&gt;&gt; =?
的加糖单码
我不知道>>=
是否实际上用于减少列表理解(但是请参阅Cirdec的答案,证明它不是),但是用<*>
来定义>>=
实际上是完全合法的。 Monad
。在数学术语中,每个Applicative
实例都会引发一个唯一的对应instance Applicative F where
pure = return
af <*> ax = af >>= \ f -> ax >>= \ x -> return (f x)
实例,在这个意义上
Applicative
只要F
有一个守法的Monad
实例,就是一个守法的fmap
实例。
如果您熟悉数学,那么这里有一个类比:
同样,对于每个monad结构,都有一个兼容的应用结构,并且对于每个应用结构都有一个兼容的fmap f ax = pure f <*> ax
(fmap
),但反过来的含义并不成立。
据我了解,应该可以实现&lt; *&gt;只使用fmap,因为适用于Maybe的情况。
我不明白你的意思。 <*>
肯定不足以定义Functor
,或者每个Applicative
都是Apply
(好吧,{{1}})。
答案 3 :(得分:3)
这个答案是对已经给出的答案的补充,只关注问题的一部分:
据我了解,应该可以仅使用
<*>
为列表实现fmap
,因为应用的是Maybe的情况。怎么样?
您好像是指this implementation:
instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just f) <*> something = fmap f something
嗯,是的,我们也可以为列表做到这一点 - 只使用fmap
,模式匹配和构造函数:
instance Applicative [] where
pure = []
[] <*> _ = []
(f:fs) <*> something = fmap f something ++ (fs <*> something)
where
[] ++ yy = ys
(x:xs) ++ ys = x : (xs++ys)
不可否认,这确实需要某种连接,因为列表比Maybes更复杂。还有其他可能适用于列表的应用实例,这些实例需要的代码少于此类所有内容。行为,但那些与默认的monad实例不兼容(这是常见的期望)。
当然,monad符号确实简化了这一点:
instance Monad m => Applicative m where
pure = return
mf <*> something = mf >>= (\f -> fmap f something) -- shorter: (`fmap` something)
...适用于Maybe
和[]
m
。