liftM(:[])如何工作

时间:2015-08-01 15:04:36

标签: haskell

我想了解下面的表达式。它会将字符列表['a','b','c']转换为字符串列表["a", "b", "c"]

liftM (:[]) "abc"

这是怎么发生的?

4 个答案:

答案 0 :(得分:12)

机器人猴头操作员(:[])只是列表中(:)的{​​{3}}和空列表[],即(:[])等同于{ {1}};反过来也可以使用列表语法编写(\x -> x:[])

以这种方式改写,我们有

(\x -> [x])

字符串文字liftM (\x -> [x]) "abc" 也只是section的语法糖,所以我们可以反过来重写上面的

"abc"

character list ['a', 'b', 'c'],给予

liftM (\x -> [x]) ['a', 'b', 'c']

fmap (\x -> [x]) ['a', 'b', 'c'] Functor实例设置[],提供

fmap = map

减少到

map (\x -> [x]) ['a', 'b', 'c']

或者,回到字符串表示法

[['a'], ['b'], ['c']]

Q.e.d。

答案 1 :(得分:10)

函数liftM转换一个函数,该函数接受输入并产生输出到一个函数,该函数在一些monad中输入并在同一个monad中产生输出。让我们看看它的定义:

liftM :: Monad m => (a -> b) -> m a -> m b
liftM f mx = mx >>= \x -> return (f x)

Haskell中的字符串是字符列表(type String = [Char]),所以

"abc" = ['a', 'b', 'c'] :: [Char]

从您的应用程序编译器推断a = Charb = [Char]m a = [Char]m = []。所以m b = [[Char]] = [String]。列表是return x = [x](>>=) = concatMap的monad。因此,如果我们专注于上面的定义,我们得到:

liftM f mx = concatMap (\x -> [f x]) mx

如果我们应用我们得到的论据:

concatMap (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ map (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ [[['a']], [['b']], [['c']]] =
[['a'], ['b'], ['c']] =
["a", "b", "c"]

答案 2 :(得分:9)

liftM相当于fmap,仅适用于monad。 (:[])使用(:)创建一个生成一个元素列表的函数。就像(+2)是一种写作(\x -> x + 2)的简洁方式一样,(:[])相当于(\x -> x : [])(\x -> [x])

然后,你的表达可能写成:

fmap (\x -> [x]) "abc"

liftM的存在反映了这样一个事实:任何合法的Monad都可以通过Functor制作成fmap f m = m >>= \x -> return (f x)。您始终可以将liftM替换为fmap,因此使用它的唯一理由是:

  • 如果您已经有fmap个实例(并且不想使用Monad GHC扩展名),则免费定义DeriveFunctor

    < / LI>
  • 一个完全可选的样式选择(如果你写的是明显的monadic代码,并认为liftM看起来比fmap好。)

答案 3 :(得分:7)

liftM定义为:

liftM f m = m >>= \x -> return (f x)

我们将liftM与列表(字符)一起使用,因此我们需要查看Monad的列表实例,以了解>>=return的位置定义:

instance Monad [] where
    return x = [x]
    xs >>= f = concat (map f xs)

因此

liftM f xs = xs >>= \x -> return (f x)
           = concat (map (\x -> [f x]) xs)

外侧的concat和内侧的[ ]相互抵消,所以

liftM f xs = map (\x -> f x) xs
           = map f xs

换句话说,列表monad中的liftM只是map

map (:[]) ['a', 'b', 'c'] = [(: []) 'a', (: []) 'b', (: []) 'c']
                          = ['a' : [], 'b' : [], 'c' : []]
                          = [['a'], ['b'], ['c']]
                          = ["a","b","c"]

因为字符串实际上只是一个字符列表。