gpt4 book ai didi

haskell - 重构使用 Reader monad 的 Haskell 函数

转载 作者:行者123 更新时间:2023-12-02 13:56:52 24 4
gpt4 key购买 nike

我有一些代码看起来有点像这样,忽略与我的问题不相关的所有代码:

import qualified Control.Monad.Reader as Reader

data FooEnv = FooEnv { bar :: Int -> Int }
type FooReader = Reader.Reader FooEnv

foo :: Int -> FooReader String
foo i = Reader.liftM show $ bar' i
where
bar' i' = do
bar'' <- Reader.asks bar
return $ bar'' i'

有没有办法重构这个?具体来说,嵌套的 bar' 函数最让我困扰。可以将其压缩为一行吗?

最佳答案

我们可以做一些等式推理。首先我们看bar' 。我会写成这样的形式

asks bar >>= \z -> return (z i)

事实证明liftM定义为liftM f m = m >>= \a -> return (f a)符合上面的模式。所以让我们将其替换为

liftM ($ i) (asks bar)

然后我们有foo作为

liftM show (liftM ($ i) (asks bar))

或者,写得特别一点

liftM show . liftM ($ i) $ asks bar

如果我们知道liftMfmap我们可能会认出Functor法律在这里发挥作用

fmap show . fmap ($ i) $ asks bar -- equals
fmap (show . ($ i)) $ asks bar

我个人不太喜欢使用 ($ i)作为一个函数,所以让我们将其重写为显式 lambda

fmap (\f -> show (f i)) (asks bar)

现在,我们可以决定消除 asks通过使用bar在调用站点(即使用 bar 作为类型 bar :: FooEnv -> Int -> Int 的函数

fmap (\f -> show (bar f i)) ask

作为最后一个技巧,我们可以使用 flipfmap 中毫无意义ped函数甚至返回asks的使用(感谢 Ørjan Johansen)

fmap (show . flip bar i) ask  -- or even
show . flip bar i <$> ask -- or even
asks (show . flip bar i)

我并不是说这是执行此任务的最可读或最美妙的方式,但您可以看到我们如何使用等式推理来削减各个部分。

关于haskell - 重构使用 Reader monad 的 Haskell 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25717316/

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