【发布时间】:2017-05-05 09:35:02
【问题描述】:
我对命令式编程有很好的掌握,但现在我自学了一个 Haskell。
我认为,我对 Monads、Functors 和 Applicatives 有很好的理论理解,但我需要一些练习。为了练习,我有时会从我目前的工作任务中得到一些东西。
我对以应用方式组合东西有点卡住了
第一个问题
我有两个验证函数:
import Prelude hiding (even)
even :: Integer -> Maybe Integer
even x = if rem x 2 == 0 then Just x else Nothing
isSmall :: Integer -> Maybe Integer
isSmall x = if x < 10 then Just x else Nothing
现在我想要由even 和isSmall 构建的validate :: Integer -> Maybe Integer
我最好的解决方案是
validate a = isSmall a *> even a *> Just a
这不是无意义的
我可以使用单子
validate x = do
even x
isSmall x
return x
但是,如果(我想)我所需要的只是一个 Applicative,为什么还要使用 Monad? (而且它仍然不是免费的)
这样做是否更好(并且更实用)?
第二个问题
现在我有两个具有不同签名的验证器:
even = ...
greater :: (Integer, Integer) -> Maybe (Integer, Integer)
-- tuple's second element should be greater than the first
greater (a, b) = if a >= b then Nothing else Just (a, b)
我需要validate :: (Integer, Integer) -> Maybe (Integer, Integer),它在输入元组上尝试greater,然后在元组的第二个元素上尝试even。
和validate' :: (Integer, Integer) -> Maybe Integer 的逻辑相同,但返回元组的第二个元素。
validate (a, b) = greater (a, b) *> even b *> Just (a, b)
validate' (a, b) = greater (a, b) *> even b *> Just b
但我想输入元组 "flows" 进入 greater,然后 "flows" 进入 snd 和 even 的某种组合和那么只有单个元素会出现在最终的 Just 中。
haskeller 会做什么?
【问题讨论】:
-
为什么所有这些都返回
Just input成功?更简单的True不会提供相同的信息吗? -
那还不是Applicative,我想学习如何使用Applicatives
-
Applicative 在这里有点滥用。您真正需要的唯一“抽象”是
Monoid。Applicative在这种情况下和Monad一样没用,呵呵。如果您想了解 Applicatives,那么寻找没有价值的人为用例可能不是一条有效的途径:) -
如果您尝试的转换可能会失败,这可能更有意义,例如 String -> Maybe Int。
-
看起来你有两个非常简单的函数:
validate k x = k x *> pure x和bool2A x = if x then pure () else empty- 然后你只有validate (bool2A . Prelude.even)和validate (bool2A . (<10))- 应该很明显如何组合函数类型a -> Bool以你想要的方式(提示:它的liftA2 (&&)- 和liftA2 (||)得到“两个条件都成立”的对偶,即“任何一个条件成立”) - 所以你的第一个例子非常简单validate (bool2A . liftA2 (&&) (<10) Prelude.even)
标签: haskell composition applicative