【问题标题】:Haskell function which acts differently depending on the monad typeHaskell 函数的作用取决于 monad 类型
【发布时间】:2017-02-02 14:20:51
【问题描述】:

我正在尝试实现一个通常将列表的第一个元素放入 monad 的函数,但如果 monad 是一个列表,它会返回整个列表:

putInMonad :: MonadPlus m => [a] -> m a
putInMonad (s:sx) = return s
putInMonad _ = mzero
putInMonad [1,2,3] :: Maybe Int

应该返回Just 1,并且

putInMonad [1,2,3] :: [] Int

应该返回[1,2,3]

有什么想法吗?

【问题讨论】:

  • 你可以使用[[]] Int作为低级monad。
  • @WillemVanOnsem 不,因为表达式return s 不包含任何关于sx 的信息;简单地提供一个具体的返回类型并没有帮助。
  • @chepner:是的,我知道对于特定的 monad,它的行为不会有所不同。我只是想用另一种方式解决问题:给它一个列表列表而不是项目列表。

标签: haskell monads alternative-functor monadplus


【解决方案1】:

在您的特定用例中,您可以利用msum

putInMonad :: MonadPlus m => [a] -> m a
putInMonad x = msum $ map return x

那么这两个例子都会起作用:

% putInMonad [1,2,3,4] :: Maybe Int
Just 1
% putInMonad [1,2,3,4] :: [Int]
[1,2,3,4]

但请注意,Maybe 并不完全是 MonadPlus,因为 mplus 没有关联性。

【讨论】:

  • 如果 MonadPlus 约束不是 OP 的硬性要求,则可以通过切换到 Alternativeasum 来避免任何关于 MonadPlus 的不安/争议。
【解决方案2】:

一般情况下,你不能这样做,因为函数在调用函数时无法知道将使用哪个Foo实例,这意味着它没有决定返回return sreturn (s:sx)的依据。

在这种特殊情况下,当FooMonadPlus 时,有一种解决方法(请参阅@marc's answer)。

【讨论】:

  • 等待投票告诉我我在技术上是正确的,还是完全错误的。
  • 您在技术上并不正确,而仅仅是因为有问题的课程是MonadPlus,它提供了marc答案中显示的解决方法。这在一般情况下是不可能的,这仍然值得一提。我建议编辑您的答案以使这种微妙之处清晰和/或指向马克的答案以进行对比。
猜你喜欢
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
相关资源
最近更新 更多