我已经了解了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]
我该如何解决这个问题?
答案 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