Aiu*_*iia 4 haskell applicative
我对 Haskell 和函数式编程还很陌生,最近我一直在学习 Functors、Applicatives 和 Monads。虽然我似乎了解基础知识,但当某些参数的类型更改为 Applicative 时,我很难找出应用函数参数的最佳/最惯用的方法。考虑以下简单代码:
myfun :: Int -> Int -> Int -> Int
myfun a b c = a + b + c -- lets pretend this does something more complicated
a = 5
b = 10
c = 20
result = myfun a b c
Run Code Online (Sandbox Code Playgroud)
使用myfun计算结果是相当简单的。但是,由于我们的要求改变,我们的投入a,b并c可能会改成即Maybe Int或[Int]甚则Int。我们仍然可以myfun通过执行以下操作之一来使用我们的未修改:
result = myfun <$> a <*> b <*> c -- either like this
result = liftA3 myfun a b c -- or like that
Run Code Online (Sandbox Code Playgroud)
然而,在实际的参数a,b并且c可能并不总是落得相同应用型内,因而这两种方法上面提到的是行不通的。在myfun不修改它的情况下仍然使该功能正常工作的最佳方法是什么?考虑a,b和的以下场景c:
Int,有些是Maybe Int(申请的结果是Maybe Int)Maybe Int,有些是Either String Int(结果可能是Maybe Int或Either String Int,如果有任何参数是Nothing或,则具有短路计算的语义Left)[Int],有些是Maybe Int(结果应该是Maybe [Int],其语义是计算所有可能的组合,就好像所有参数都是[Int],然后将其包装在 a 中Just,除非 Maybies 是Nothing,在这种情况下我们短路到Nothing)非常感谢任何见解!
这取决于你想要发生什么。可能没有任何通用的方法来组合不同的 monad。一般来说,当你真正需要组合不同的 monad 时,你经常(总是?)使用 monad 转换器,但通常有更简单的解决方案。您提到的特定组合就是这种情况。
在所有这些特定情况下,您可以将一个 monad 转换为另一个。在下面,我将给出一些可以做到这一点的方法的例子。
其中一些示例使用来自 的函数Data.Maybe,所以我将从:
import Data.Maybe
Run Code Online (Sandbox Code Playgroud)
它在第一个示例中不是必需的,但在第二个和第三个示例中是必需的。
Int,一些Maybe Int如果您有Int和Maybe Int值的组合,则解决方案很简单。只需将Int值提升到Maybe Int. 您可以为此使用Just或pure。这是一个使用示例pure:
a1 = 5
b1 = Just 10
c1 = 20
result1 :: Maybe Int
result1 = myfun <$> pure a1 <*> b1 <*> pure c1
Run Code Online (Sandbox Code Playgroud)
结果是Just 35。
Maybe Int,一些Either String Int您可以通过将一个 monad 转换为另一个来重复这个技巧。如果您对案例有用,则可以将Maybe Int值转换为Either String Int值。您还可以通过丢弃值将值转换为值。StringNothingEither String IntMaybe IntString
这是一个转换Maybe Int为的示例Either String Int:
a2 = Just 5
b2 = Right 10
c2 = Left "Boo!"
result2 :: Either String Int
result2 = myfun <$> maybe (Left "No value") Right a2 <*> b2 <*> c2
Run Code Online (Sandbox Code Playgroud)
此组合使用maybe来自的函数Data.Maybe。结果是Left "Boo!"。
[Int],一些Maybe Int你可以很容易地Maybe Int变成[Int]使用maybeToList:
a3 = [5, 10]
b3 = Nothing
c3 = Just 20
result3 :: [Int]
result3 = myfun <$> a3 <*> maybeToList b3 <*> maybeToList c3
Run Code Online (Sandbox Code Playgroud)
这样做的结果是[]因为Nothing转换为[],这就是Applicative列表的工作方式。这可能不是你想要的,但我希望这些例子能激励你想出你喜欢的作品。