【发布时间】:2011-09-21 17:26:44
【问题描述】:
我正在阅读 Conor McBride 和 Ross Paterson 的“Functional Pearl / Idioms: applicative programming with effects:”(new 版本,标题中带有“idioms”)。我在练习 4 中遇到了一点困难,下面将对此进行解释。任何提示将不胜感激(特别是:我应该开始写fmap 和join 还是return 和>>=?)。
问题陈述
你想在哪里创建一个instance Monad []
return x = repeat x
和ap = zapp。
标准库函数
如第 p.论文的 2,ap 将一元函数值应用于一元值。
ap :: Monad m => m (s -> t) -> m s -> m t
ap mf ms = do
f <- mf
s <- ms
return (f s)
我用规范符号将其扩展为,
ap mf ms = mf >>= (\f -> (ms >>= \s -> return (f s)))
特定于列表的函数zapp(“zippy 应用程序”)将一个列表中的函数应用于另一个列表中的对应值,即,
zapp (f:fs) (s:ss) = f s : zapp fs ss
我的困难
请注意,在扩展形式中,mf :: m (a -> b) 在我们的例子中是函数[(a -> b)] 的列表。所以,在>>=的第一个应用中,我们有
(f:fs) >>= mu
在哪里mu = (\f -> (ms >>= \s -> return (f s)))。现在,我们可以将fs >>= mu 作为子程序调用,但这并不知道要删除ms 的第一个元素。 (回想一下,我们希望结果列表是 [f1 s1, f2 s2, ...]。我试图破解一些东西,但是......正如预期的那样,它没有用......任何帮助将不胜感激。
提前致谢!
编辑 1
我想我已经成功了;首先,我按照用户“comonad”的建议,用 fmap 和 join 重写了 ap。
我的信念飞跃假设fmap = map。如果有人能解释如何到达那里,我将非常感激。在此之后,很明显join 在用户“comonad”建议的列表列表中起作用,并且应该是对角线\x -> zipWith ((!!) . unL) x [0..]。我的完整代码是这样的:
newtype L a = L [a] deriving (Eq, Show, Ord)
unL (L lst) = lst
liftL :: ([a] -> [b]) -> L a -> L b
liftL f = L . f . unL
joinL :: L (L a) -> L a
joinL = liftL $ \x -> zipWith ((!!) . unL) x [0..]
instance Functor L where
fmap f = liftL (map f)
instance Monad L where
return x = L $ repeat x
m >>= g = joinL (fmap g m)
希望是对的(似乎是论文第 18 页上的“解决方案”)...谢谢大家的帮助!
【问题讨论】:
-
关于
fmap:Applicative法律包括身份pure f <*> x=f <$> x。您应该能够使用它将fmap显示为map。是的,join采用嵌套列表的对角线——作为后续练习,您可以尝试展示对角线在不同长度的列表上定义不明确如何违反单子定律。