liftM(:[])如何工作

ako*_*nsu 7 haskell

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

liftM (:[]) "abc"
Run Code Online (Sandbox Code Playgroud)

这是怎么发生的?

Cac*_*tus 14

机器人猴子头操作(:[])仅仅是部分名单利弊(:)和空列表[],即(:[])相当于(\x -> x:[]); 反过来也可以使用列表语法编写(\x -> [x]).

我们改写了这种方式

liftM (\x -> [x]) "abc"
Run Code Online (Sandbox Code Playgroud)

字符串文字"abc"也只是字符列表的['a', 'b', 'c']语法糖,所以我们可以反过来重写上面的

liftM (\x -> [x]) ['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

liftM只是fmap来自黑暗的日子,Functor而不是超级的Monad,给予

fmap (\x -> [x]) ['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

集合的Functor实例,给予[]fmap = map

map (\x -> [x]) ['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

减少到

[['a'], ['b'], ['c']]
Run Code Online (Sandbox Code Playgroud)

或者,回到字符串表示法

["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)

QED

  • +1"机器人猴子操作员"我从来没有听说过这个术语,从现在起我的haskell编程经验将更加精彩! (4认同)

aem*_*xdp 12

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

liftM :: Monad m => (a -> b) -> m a -> m b
liftM f mx = mx >>= \x -> return (f x)
Run Code Online (Sandbox Code Playgroud)

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

"abc" = ['a', 'b', 'c'] :: [Char]
Run Code Online (Sandbox Code Playgroud)

从你的应用程序编译器推断a = Char,b = [Char],m a = [Char],m = [].所以m b = [[Char]] = [String].列表是monad where return x = [x](>>=) = concatMap.因此,如果我们专门定义上述定义,我们得到

liftM f mx = concatMap (\x -> [f x]) mx
Run Code Online (Sandbox Code Playgroud)

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

concatMap (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ map (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ [[['a']], [['b']], [['c']]] =
[['a'], ['b'], ['c']] =
["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)


dup*_*ode 9

liftM等同于fmap,仅专门用于monad.(:[])用于(:)创建一个生成一个元素列表的函数.就像(+2)是一种紧凑的写作方式(\x -> x + 2),(:[])相当于(\x -> x : []),或(\x -> [x]).

那么你的表达可能写成:

fmap (\x -> [x]) "abc"
Run Code Online (Sandbox Code Playgroud)

的存在liftM反映了一个事实,任何合法的Monad可以做成Functor这样做fmap f m = m >>= \x -> return (f x).您可以随时更换liftMfmap,所以唯一的原因使用它是:

  • fmap如果你已经拥有一个Monad实例(并且不想使用DeriveFunctorGHC扩展),那么可以免费定义

  • 一个完全可选的样式选择(如果您正在编写明显的monadic代码并且感觉liftM看起来更好fmap).


mel*_*ene 7

liftM 定义为:

liftM f m = m >>= \x -> return (f x)
Run Code Online (Sandbox Code Playgroud)

我们使用liftM与(的角色)的列表,所以我们需要看的列表实例Monad,看看如何>>=return定义:

instance Monad [] where
    return x = [x]
    xs >>= f = concat (map f xs)
Run Code Online (Sandbox Code Playgroud)

从而

liftM f xs = xs >>= \x -> return (f x)
           = concat (map (\x -> [f x]) xs)
Run Code Online (Sandbox Code Playgroud)

concat在外面和[ ]在里面相互抵消,所以

liftM f xs = map (\x -> f x) xs
           = map f xs
Run Code Online (Sandbox Code Playgroud)

换句话说,liftM在列表monad是简单的map.

map (:[]) ['a', 'b', 'c'] = [(: []) 'a', (: []) 'b', (: []) 'c']
                          = ['a' : [], 'b' : [], 'c' : []]
                          = [['a'], ['b'], ['c']]
                          = ["a","b","c"]
Run Code Online (Sandbox Code Playgroud)

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