Haskell函数根据monad类型的不同而不同

时间:2017-02-02 14:20:51

标签: haskell monads

我正在尝试实现一个通常将列表的第一个元素放在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]

有什么想法吗?

2 个答案:

答案 0 :(得分:5)

在您的特定用例中,您可以利用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没有关联。

答案 1 :(得分:1)

通常,您不能这样做,因为函数在调用函数时无法知道将使用哪个Foo实例,这意味着它没有决定返回return s或{的依据。 {1}}。

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