我很难理解liftM2haskell的工作原理。我编写了以下代码,但未输出任何内容。
import Control.Monad
main = liftM2 (\a b -> putStrLn$show$(+) a b) readLn readLn
Run Code Online (Sandbox Code Playgroud)
它有助于从以下类型开始liftM2:
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Run Code Online (Sandbox Code Playgroud)
第一个参数是2个参数的函数,例如(+)。通常,您将这样使用(+):
> 3 + 5
8
Run Code Online (Sandbox Code Playgroud)
但是,您没有两个type值Num a => a;您readLn :: Read a => IO a用来获取type的值Num a => IO a。如果尝试直接添加这些值:
:t (+) readLn readLn
(+) readLn readLn :: (Read a, Num (IO a)) => IO a
Run Code Online (Sandbox Code Playgroud)
它需要IO a有一个Num实例。也就是说,您不想添加readLn; 的返回值。您想添加包装在这些返回值中的数字。您可以明确地做到这一点:
do
x <- readLn
y <- readLn
return $ x + y
Run Code Online (Sandbox Code Playgroud)
或者,您可以“修改” (+)以隐式解开参数,然后包装结果。就是liftM2这样:它接受一个2参数的函数,并将其“提升”到monad中,以便它可以处理包装的值。
> :t (+)
(+) :: Num a => a -> a -> a
> :t liftM2 (+)
liftM2 (+) :: (Num r, Monad m) => m r -> m r -> m r
Run Code Online (Sandbox Code Playgroud)
所以(+) 3 5 :: Num a => a,liftM2 (+) $ (return 3) (return 5) :: (Monad m, Num a) => m a。前者评估为8,后者评估为return 8(对于return特定monad 执行任何操作)。一些非IO示例:
> (liftM2 (+)) (Just 3) (Just 5)
Just 8
> (liftM2 (+)) [3] [5]
[8]
> (liftM2 (+)) (Right 3) (Right 5)
Right 8
Run Code Online (Sandbox Code Playgroud)
liftM2与...非常相似map; 实际上,liftM(提升1参数功能的版本)只是的另一种名称map。
| 归档时间: |
|
| 查看次数: |
930 次 |
| 最近记录: |