gpt4 book ai didi

haskell - 转换 a -> a -> Maybe a 以采用 a 和 Maybe a 的任意组合

转载 作者:行者123 更新时间:2023-12-01 23:15:59 24 4
gpt4 key购买 nike

我有一个类型为 Integral => a -> a -> Maybe a 的函数 f。这意味着

f 1 2

是有效的代码,但是自然的组合,例如

f (f 3 4) 5
f 6 (f 7 8)
f (f 9 10) (f 11 12)

无效。

有一些方法可以让它发挥作用。例如,

f 6 =<< f 7 8

这是我所知道的对于案例 2 最好的方法。对于案例 3,

join $ f <$> f 9 10 <*> f 11 12

是我能想到的最好的,但额外的 join 却显得很突出。我对情况 1 没有什么好主意。除此之外,令我困扰的是我想出的语法并不“一致”——我基本上完成了相同的事情,但语法非常不同。

是否有一个标准/惯用的结构允许我将 f 转换为 Maybe a -> a -> Maybe a, a -> Maybe a -> Maybe aMaybe a -> Maybe a -> Maybe a,具有良好且一致的语法?

最佳答案

原始解决方案

让我们为第一种情况创建一个实用函数:

lift :: (a -> b -> Maybe c) -> Maybe a -> b -> Maybe c
lift _ Nothing _ = Nothing
lift f (Just a) b = f a b

情况1:

lift f (f 3 4) 5

情况2:

f 6 =<< f 7 8

情况3:

lift f (f 9 10) =<< f 11 12

虽然它看起来更一致,但以我的拙见,它仍然看起来很丑。也许其他人可以提供更好的解决方案。

推荐解决方案

编辑:在思考我的解决方案后,我意识到它可以推广:

(<&>) :: (Applicative m, Monad m) => m (a -> m b) -> m a -> m b
f <&> a = join $ f <*> a
infixl 4 <&>

情况1:

f <$> f 3 4 <&> pure 5

情况2:

f <$> pure 6 <&> f 7 8

情况3:

f <$> f 9 10 <&> f 11 12

这适用于任意数量的函数:

f <$> a <&> b             -- f :: a -> a -> Maybe a

f <$> a <*> b <&> c -- f :: a -> a -> a -> Maybe a

f <$> a <*> b <*> c <&> d -- f :: a -> a -> a -> a -> Maybe a

等等......

替代解决方案

编辑: 同意 @n.m。最好的解决方案是将函数的类型签名更改为 Maybe a -> Maybe a -> Maybe a 并在必要时使用 Just

情况1:

f (f (Just 3) (Just 4)) (Just 5)

情况2:

f (Just 6) (f (Just 7) (Just 8))

情况3:

f (f (Just 9) (Just 10)) (f (Just 11) (Just 12))

最简单的解决方案总是最好的。

编辑:实际上,回想起来,我以前的解决方案要简单得多。

关于haskell - 转换 a -> a -> Maybe a 以采用 a 和 Maybe a 的任意组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26520261/

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