我想了解下面的表达式.它将字符['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
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)
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).您可以随时更换liftM的fmap,所以唯一的原因使用它是:
fmap如果你已经拥有一个Monad实例(并且不想使用DeriveFunctorGHC扩展),那么可以免费定义
一个完全可选的样式选择(如果您正在编写明显的monadic代码并且感觉liftM看起来更好fmap).
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)
因为字符串实际上只是一个字符列表.
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |