Haskell 函数根据 monad 类型的不同而不同
Haskell function which acts differently depending on the monad type
我正在尝试实现一个通常将列表的第一个元素放在 monad 中的函数,但是如果 monad 是一个列表,它 return 就是整个列表:
putInMonad :: MonadPlus m => [a] -> m a
putInMonad (s:sx) = return s
putInMonad _ = mzero
putInMonad [1,2,3] :: Maybe Int
应该returnJust 1
,
putInMonad [1,2,3] :: [] Int
应该return[1,2,3]
.
有什么想法吗?
一般情况下,你不能这样做,因为函数无法知道调用函数时将使用哪个Foo
实例,这意味着它没有决定return return s
或 return (s:sx)
.
在这种特殊情况下,当 Foo
为 MonadPlus
时,有一个解决方法(参见 )。
在您的特定 use-case 中,您可以利用 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
没有关联。
我正在尝试实现一个通常将列表的第一个元素放在 monad 中的函数,但是如果 monad 是一个列表,它 return 就是整个列表:
putInMonad :: MonadPlus m => [a] -> m a
putInMonad (s:sx) = return s
putInMonad _ = mzero
putInMonad [1,2,3] :: Maybe Int
应该returnJust 1
,
putInMonad [1,2,3] :: [] Int
应该return[1,2,3]
.
有什么想法吗?
一般情况下,你不能这样做,因为函数无法知道调用函数时将使用哪个Foo
实例,这意味着它没有决定return return s
或 return (s:sx)
.
在这种特殊情况下,当 Foo
为 MonadPlus
时,有一个解决方法(参见
在您的特定 use-case 中,您可以利用 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
没有关联。