Предположим, у меня есть функция (plusOne
в приведенном ниже примере), которая принимает и возвращает только Int
.Но у меня нет Int
;вместо этого у меня есть Maybe Int
;и если это Maybe Int
содержит значение, то я хочу передать его plusOne
и получить Just
того, что plusOne
возвращает, или, если это скорее 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 (SomeData Int)
из моего Maybe 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
) требуют прохождения анонимной лямбда-функции, которая, на мой взгляд, не должна быть необходимой и толькослужит для того, чтобы заглушить код.Есть ли способ избежать этого?Можно ли как-то «поднять» конструктор someData
так же, как я мог бы поднять plusOne
в первом фрагменте?