Return Do-notation 中的一些值 - Haskell

Return some values in Do-notation - Haskell

我了解了 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]

我该如何解决这个问题?

您想使用 monad 列表,monad 列表中的 return 表示类似于 "add the value to the monad context" 或代码中的

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

do 符号被脱糖为

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

return 在 Haskell 中的工作方式与在命令式语言中的工作方式不同。在这里写两个 return 是没有意义的,因为第二个 'overwrites' 第一个

do-notation 专门用于处理 Monads,所以你有一个正确的类型,但你使用的函数不正确。我会这样做:

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

这是有效的原因是我用 [a] 类型的东西结束我的表达式。您不一定必须使用 return!

这里使用do-notation有点混乱,所以最好使用concatMap :: (a -> [b]) -> [a] -> [b]:

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