【问题标题】:What is the difference between these mondaic functions?这些 mondaic 函数有什么区别?
【发布时间】:2020-06-18 18:37:09
【问题描述】:

所以我有这两个功能:

filterM _ [] = []
filterM p (x:xs) = do
                  n <- p x
                  ys <- filterM p xs
                  return (if n then x:ys else x:xs)

filterM _ [] = return []
filterM p (x:xs) = do
                  n <- p x
                  ys <- filterM p xs
                  return (if n then x:ys else x:xs)

导致以下输入的这些结果:filterM (\x -&gt; [True,False]) [0..3]

[]

[[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3]]

为什么return 会对执行产生如此大的影响?

【问题讨论】:

  • return [] 表示在列表[[]] 的上下文中,这对于ys 是必需的,因为如果我们返回[],那么ys“不带值”,因此结果也将是一个空列表。
  • @WillemVanOnsem 哦,当然。 return 将值包装到 monad 中。这个是从 [] monad 派生的,因此导致 [] 被包裹在 []
  • 强烈建议编写类型签名以避免这些问题。

标签: haskell monads


【解决方案1】:

让我们看一个我们调用的简单案例:

filterM (const [True, False]) [0]

我们预计这将返回 [[0], [0]]。如果我们看一下第一个实现,我们会看到这将导致:

filterM (const [True, False]) (0:[]) = do
    n <- [True, False]
    ys <- filterM (const [True, False]) []
    return (if n then 0:ys else 0:[])

如果我们采用第一个实现,filterM (const [True, False]) [] 将导致[]。所以这意味着它看起来像:

-- first implementation
filterM (const [True, False]) (0:[]) = do
    n <- [True, False]
    ys <- []
    return (if n then 0:ys else 0:[])

由于instance Monad []the &gt;&gt;= is implemented as

instance Monad [] where
    return x = [x]
    xs >>= f = [y | x <- xs, y <- f x]

这意味着如果xs 为空,那么结果也将为空。

在第二个实现中,return [] 将产生[[]],因此一个单例列表,其中单个元素是一个空列表。在这种情况下,它看起来像:

-- second implementation
filterM (const [True, False]) (0:[]) = do
    n <- [True, False]
    ys <- [[]]
    return (if n then 0:ys else 0:[])

因此,这意味着我们枚举列表,ys 将采用值 [],因此它将产生一个列表 [[0], [0]]

通常过滤器不会在这两种情况下添加x,此外,您可能希望生成x:ysys;不是x:ysx:xs。因此,正确的实现是:

filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM _ [] = return []
filterM p (x:xs) = do
    n <- p x
    ys <- filterM p xs
    return (if n then x:ys else ys)

【讨论】:

    猜你喜欢
    • 2020-06-28
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    相关资源
    最近更新 更多