Haskell中的liftM和mapM有什么区别

Haskell中的liftM和mapM有什么区别,haskell,functional-programming,monads,combinators,Haskell,Functional Programming,Monads,Combinators,liftM和mapM的功能有什么区别?首先,类型不同: liftM :: (Monad m) => (a -> b) -> m a -> m b mapM :: (Monad m) => (a -> m b) -> [a] -> m [b] liftM将类型为a->b的函数提升为一元对应函数。 mapM将一个函数应用于一个值列表,该函数生成一个一元值,并生成嵌入一元值的结果列表 示例: > liftM (map toUpper) getLi

liftM和mapM的功能有什么区别?

首先,类型不同:

liftM :: (Monad m) => (a -> b) -> m a -> m b
mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
liftM
将类型为
a->b
的函数提升为一元对应函数。
mapM
将一个函数应用于一个值列表,该函数生成一个一元值,并生成嵌入一元值的结果列表

示例:

> liftM (map toUpper) getLine
Hallo
"HALLO"

> :t mapM return "monad"
mapM return "monad" :: (Monad m) => m [Char]
。。。请注意,
map
mapM
不同!例如

> map (x -> [x+1]) [1,2,3]
[[2],[3],[4]]
> mapM (x -> [x+1]) [1,2,3]
[[2,3,4]]

他们并没有真正的联系。我会尽力解释他们每个人都做了什么。我想你对单子有一个基本的了解

liftM::Monad m=>(a->b)->(ma->mb)
允许您在Monad中使用普通函数。它接受一个函数
a->b
,并将其转换为一个函数
ma->mb
,该函数的作用与原始函数完全相同,但它是在单子中完成的。结果函数不会对monad“做”任何事情(它不能,因为原始函数不知道它在monad中)。例如:

main :: IO ()
main = do
    output <- liftM ("Hello, " ++) getLine
    putStrLn output
这张照片是:

1
2
3
[(),(),()]

它所做的是迭代列表,对列表中的每个元素应用
(putStrLn.show)
(具有打印每个数字的IO效果),并将数字转换为
()
值。结果列表由
[(),(),()]
--putStrLn

的输出组成。其他答案已经很好地解释了这一点,因此我只想指出,在真实的Haskell代码中,通常会看到使用
fmap
而不是
liftM
,as
fmap
只是类型类
Functor
中更通用的版本。由于所有行为良好的
Monad
s都应该是
Functor
的实例,它们应该是等价的

您还可以看到操作员
用作
fmap
的同义词


另外,
mapM f=序列。映射f,因此您可以将其视为将值列表转换为操作列表,然后依次运行操作,将结果收集到列表中。

liftM
mapM
非常不同,从它们的类型和实现可以看出:

mapM         :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as    =  sequence (map f as)

liftM        :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1   = do { x1 <- m1; return (f x1) }
mapM::Monad m=>(a->mb)->[a]->m[b]
mapM f as=序列(map f as)
liftM::(单子m)=>(a1->r)->M1->MR

liftM f m1=do{x1@larsmans,这个问题与mapM无关。@mgiuca:你说得对。对不起,我想我应该仔细阅读。此外,如果你只关心
mapM
的一元效应,而不关心返回的列表,你可以使用
mapM
mapM
函数的类型是
Monad m=>(a->mb)->[a]->m()
,它在putStrLn示例中很有用,您可能对单位列表不感兴趣。@Tom Lokhorst Yep,没错。(我找不到一个有用的示例,结果对IO monad很重要。)为什么mapM会将数字转换为“()”?@Luke the
putStrLn::String->IO()
返回一个单位值(即
()
)。下面是另一个示例:
mapM(\x->putStrLn(show x)>>返回(x+1))[1,2,3]
。这将返回一个整数列表而不是单位。它是
(\x->[x+1])
在lambda for map中?我尝试了不带反斜杠的x语法,在表达式上下文中得到了
模式语法:x->[x+1]
。我是Haskell新手,所以我可能在这里遗漏了一些东西。
mapM         :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as    =  sequence (map f as)

liftM        :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1   = do { x1 <- m1; return (f x1) }