【发布时间】:2019-03-20 13:09:18
【问题描述】:
假设我有一个只接受并返回Int 的函数(在下面的示例中为plusOne)。但我没有Int;相反,我有一个Maybe Int;如果这个Maybe Int 包含一个值,那么我想将它传递给plusOne 并得到plusOne 返回的Just,或者如果它是Nothing,那么我希望这个Nothing 传播。
在这种情况下,我们有 liftM 以优雅的方式编写代码:
import Control.Monad
plusOne :: Int -> Int
plusOne n =
n+1 -- a very complicated computation that is failsafe
main =
let n = Just 15 -- a very complicated computation that can fail
in let res = liftM plusOne n
in print res
到目前为止一切顺利。但是,这样的事情也可以用构造函数来完成吗?
忘记plusOne。现在我有:data SomeData = SomeData Int 并想从我的Maybe Int 获得一个Maybe (SomeData Int)。该解决方案似乎明显不那么优雅:
import Control.Monad
data SomeData = SomeData Int
deriving Show -- so that print works
main =
let n = Just 15
in let res = n >>= (\nn -> Just (SomeData nn))
-- alternatively: in let res = liftM (\nn -> SomeData nn) n
in print res
上述两种解决方案(使用>>= 或liftM)都需要通过一个匿名 lambda 函数,根据我的直觉,这不是必需的,只会破坏代码。有没有办法避免它?我可以像在第一个 sn-p 中提升 plusOne 一样以某种方式“提升”someData 构造函数吗?
【问题讨论】:
-
\nn -> Just (SomeData nn)只是Just . SomeData。 -
let res = liftM (\nn -> SomeData nn)与liftM SomeData相同。 (或者确实是fmap SomeData- 这是个人选择,但我更喜欢调用函数fmap。) -
现在无法编辑,但我显然是指上面的“与
let res = liftM SomeData相同” -
@RobinZigmond 哇,谢谢!不知道构造函数算作函数。
标签: haskell constructor monads maybe lifting