gpt4 book ai didi

list - Haskell:如何简化或消除 liftM2?

转载 作者:行者123 更新时间:2023-12-02 22:35:18 24 4
gpt4 key购买 nike

考虑我编写的以下代码:

import Control.Monad

increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = liftM2 mod ps [10]
let next = liftM2 (*) ps [10]
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = liftM2 (+) [x] [y..9]

其中“increasing n”应返回一个 n 位数字的列表,其数字从左到右增加(或保持不变)。

有办法简化这个吗? 在我看来,到处使用“let”和“liftM2”看起来很难看。我认为我错过了有关列表单子(monad)的一些重要内容,但我似乎无法摆脱它们。

最佳答案

好吧,至liftM函数 go,我首选的使用方法是 Control.Applicative 中定义的组合器。使用这些,你可以写 last = mod <$> ps <*> [10]ap来自 Control.Monad 的函数做同样的事情,但我更喜欢中缀版本。

什么(<$>)(<*>)像这样:liftM2变成一个函数a -> b -> c进入函数m a -> m b -> m c 。普通liftM只是 (a -> b) -> (m a -> m b) ,与 fmap 相同还有(<$>) .

如果对多参数函数执行此操作会发生什么?它变成类似 a -> b -> c -> d进入m a -> m (b -> c -> d) 。这就是ap(<*>)进来:他们所做的就是把类似 m (a -> b)进入m a -> m b 。因此,您可以继续按照这种方式串接任意数量的参数。

<小时/>

也就是说,特拉维斯·布朗(Travis Brown)是正确的,在这种情况下,您似乎并不真正需要上述任何内容。事实上,您可以大大简化您的功能:例如, lastnext可以写为映射到同一列表的单参数函数,ps ,和zipWithzip 相同和一个 map 。所有这些 map 都可以组合起来并插入 alts功能。这使得alts单参数函数,消除 zip以及。最后,concat可以与 map 结合使用如concatMap或者,如果愿意,(>>=) 。最终结果如下:

increasing' :: Integer -> [Integer]
increasing' 1 = [1..9]
increasing' n = increasing' (n - 1) >>= alts
where alts x = map ((x * 10) +) [mod x 10..9]

请注意,我为从您的版本获得该版本所做的所有重构纯粹是语法,仅应用不应影响函数结果的转换。等式推理和引用透明性很好!

关于list - Haskell:如何简化或消除 liftM2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3989353/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com