Haskell中的liftM和mapM有什么区别
liftM 和mapM 函数有什么区别?
What is the difference between the functions liftM and mapM?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
liftM 和mapM 函数有什么区别?
What is the difference between the functions liftM and mapM?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(4)
他们并没有真正的关系。我将尝试解释它们每个人的作用。我假设您对 monad 是什么有基本的了解。
liftM :: Monad m =>; (a→b)→ (ma -> mb)
允许您在 monad 中使用普通函数。它需要一个函数a ->; b
,并将其转换为函数ma -> m b
,它与原始函数执行完全相同的操作,但在 monad 中执行。生成的函数不会对 monad “做”任何事情(它不能,因为原始函数不知道它在 monad 中)。例如:函数
("Hello, " ++) :: String -> String
在字符串前面添加“Hello,”。将其传递给 liftM 会创建一个 IO String 类型的函数 -> IO String——现在你有了一个可以在 IO monad 中工作的函数。它不执行任何 IO,但它可以将 IO 操作作为输入,并产生 IO 操作作为输出。因此,我可以将getLine
作为输入传递,它将调用getLine
,在结果前面添加“Hello,”,并将其作为 IO 操作返回。mapM :: Monad m =>; (a→mb)→ [一]-> m [b]
是完全不同的;请注意,与 liftM 不同,它采用一元函数。例如,在 IO monad 中,它的类型为(a -> IO b) -> [一]-> IO [b]
。它与普通的map
函数非常相似,只是它将单子操作应用于列表,并生成包装在单子操作中的结果列表。例如(一个非常糟糕的例子):它打印:
它所做的是迭代列表,将
(putStrLn . show)
应用于列表中的每个元素(具有打印出每个元素的 IO 效果)数字),并将数字转换为()
值。结果列表由[(), (), ()]
组成 -putStrLn
的输出。They aren't really related. I'll try to explain what each of them does. I assume you have a basic understanding of what a monad is.
liftM :: Monad m => (a -> b) -> (m a -> m b)
lets you use an ordinary function in a monad. It takes a functiona -> b
, and turns it into a functionm a -> m b
, that does exactly the same thing as the original function, but does it in a monad. The resulting function doesn't "do" anything to the monad (it can't, because the original function didn't know it was in a monad). For example:The function
("Hello, " ++) :: String -> String
prepends "Hello, " to a string. Passing it toliftM
creates a function of typeIO String -> IO String
-- now you have a function that works in the IO monad. It doesn't do any IO, but it can take an IO action as input, and produces an IO action as output. Therefore, I can passgetLine
as input, and it will callgetLine
, prepend "Hello, " to the front of the result, and return that as an IO action.mapM :: Monad m => (a -> m b) -> [a] -> m [b]
is quite different; note that unlikeliftM
, it takes a monadic function. For example, in the IO monad, it has type(a -> IO b) -> [a] -> IO [b]
. It is very much like the ordinarymap
function, only it applies a monadic action to a list, and produces a result list wrapped in a monadic action. For example (a pretty bad one):This prints:
What it is doing is iterating over the list, applying
(putStrLn . show)
to each element in the list (having the IO effect of printing out each of the numbers), and also transforming the numbers into the()
value. The resulting list consists of[(), (), ()]
-- the output ofputStrLn
.首先,类型不同:
liftM 提升类型为 a -> 的函数。 b 到一元对应物。
mapM
应用一个函数,该函数将产生一个单子值到一个值列表,从而产生嵌入在该单子中的结果列表。示例:
...请注意
map
和mapM
不同!例如First, the types differ:
liftM
lifts a function of typea -> b
to a monadic counterpart.mapM
applies a function which yields a monadic value to a list of values, yielding list of results embedded in the monad.Examples:
... note that
map
andmapM
differ! E.g.其他答案已经解释得很好,所以我只想指出,在真正的 Haskell 代码中,您通常会看到使用
fmap
而不是liftM
,如fmap< /code> 只是类型类
Functor
中更通用的版本。由于所有行为良好的 Monad 也应该是 Functor 的实例,因此它们应该是等效的。您还可能会看到运算符
<$>
用作fmap
的同义词。另外,mapM f = 序列。 map f,因此您可以将其视为将值列表转换为操作列表,然后依次运行操作,将结果收集到列表中。
The other answers have already explained it well, so I will just point out that you will usually see
fmap
used instead ofliftM
in real Haskell code, asfmap
is just a more general version in the type classFunctor
. As all well-behavedMonad
s should be instances ofFunctor
as well, they should be equivalent.You may also see the operator
<$>
used as a synonym forfmap
.Also,
mapM f = sequence . map f
, so you can think of it as turning a list of values into a list of actions, and then running the actions one after another, collecting the results in a list.liftM
和mapM
非常不同,您可以通过它们的类型和实现看到这一点:因此,虽然
mapM
将一元函数应用于每个元素一个列表,liftM
在一元设置中应用一个函数。liftM
andmapM
are quite different, as you can see via their types and their implementation:so while
mapM
applies a monadic function to each element of a list,liftM
applies a function in a monadic setting.