gpt4 book ai didi

haskell - 使一元代码更短

转载 作者:行者123 更新时间:2023-12-04 03:37:48 25 4
gpt4 key购买 nike

考虑以下代码:

transform :: Foo -> Bar
transform foo =
case foo of
Foo1 x -> Foo1 x
Foo2 x y -> Foo2 x (transform y)
Foo3 x y z -> Foo3 x (transform y) (transform z)

现在假设由于某种原因我将其更改为在 monad 中工作(例如,因为我有状态我想随身携带或其他)。现在我们有
transform :: Foo -> State Int Bar
transform foo =
case foo of
Foo1 x -> return $ Foo1 x
Foo2 x y -> do
y' <- transform y
return $ Foo2 x y'
Foo3 x y z -> do
y' <- transform y
z' <- transform z
return $ Foo3 x y' z'

好吧,一切正常,但是……我们可以改进吗?我有一种挥之不去的感觉,我应该能够定义一些漂亮的中缀函数来使它看起来更好,但每次我试图弄清楚如何,我的大脑会在一段时间后变得 NumPy ......

最佳答案

你的直觉是对的。这是ap的作用Monad 中的函数类,或等同于 <*> Applicative 中的运算符类,几乎所有的 monad 都实现了(实际上将来会成为 Monad 的父类(super class))。

这是它的类型:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b

所以它基本上应用了一个包装函数 a -> b到一个包装好的 a返回一个包装好的 b .它相当于:
mf <*> mx = do
f <- mf
x <- mx
return $ f x

以下是如何在您的案例中使用它,强调不同案例之间的相似性:
transform foo =
case foo of
Foo1 x -> return Foo1 <*> return x
Foo2 x y -> return Foo2 <*> return x <*> transform y
Foo3 x y z -> return Foo3 <*> return x <*> transform y <*> transform z

这可以通过考虑 return f <*> return x == return (f x) 来缩短。 :
transform foo =
case foo of
Foo1 x -> return $ Foo1 x
Foo2 x y -> return (Foo2 x) <*> transform y
Foo3 x y z -> return (Foo3 x) <*> transform y <*> transform z

更进一步,通过使用运算符 <$>相当于 fmap来自 Functor类(class):
transform foo =
case foo of
Foo1 x -> return $ Foo1 x
Foo2 x y -> Foo2 x <$> transform y
Foo3 x y z -> Foo3 x <$> transform y <*> transform z

关于haskell - 使一元代码更短,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21797980/

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