在Do-notation中返回一些值 - Haskell

时间:2015-04-10 17:34:44

标签: haskell syntax monads

我已经了解了do-notation。我现在想开发一个转换列表的函数。

我希望它表现得像这样:

λ> transform 42 [1, 2, 3, 4, 5, 6]
[1, 42, 2, 42, 3, 42, 4, 42, 5, 42, 6, 42]

我目前的代码是:

transform :: a -> [a] -> [a]
transform new_number xs = do x <- xs
                            return x
                            return new_number

...我的结果是:

λ> transform 42 [1, 2, 3]
[42,42,42]

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:5)

return在Haskell中的工作方式与在命令式语言中的工作方式相同。在这里写两个return是没有意义的,因为第二个&#39}覆盖了&#39;第一个。

do - 符号专门用于处理 Monads ,因此您的类型正确,但您使用的功能不正确。我就是这样做的:

transform :: a -> [a] -> [a]
transform new xs = do
  x <- xs
  [x,new]

这个有效的原因是我用类型[a]来结束我的表达。您不一定要使用return

使用do - 表示法有点令人困惑,因此使用concatMap :: (a -> [b]) -> [a] -> [b]可能更好:

transform new xs = concatMap (\x -> [x,new]) xs

答案 1 :(得分:1)

你想使用monad列表,monad列表中的return意味着“将值添加到monad上下文”或代码中

do x <- xs
   return x

等于

do x <- xs
   [x]

因此你转换函数应该是

tranform :: a -> [a] -> [a]
tranform new_number xs = do x <- xs
                            x: [new_number]

这相当于

tranform new_number xs = concatMap (:[new_number]) xs

符号是desugar

xs >>= \x -> x:[new_number]

并且monad列表的绑定运算符与concatMap

相关
concatMap :: (a -> [b]) -> [a] -> [b]
(>>=) :: Monad m => m a -> (a -> m b) -> m b

在这种情况下,m a是monad列表[] a