Я написал эту функцию:
appFunc :: Integer -> Integer -> Bool -> Maybe (Integer,Integer)
appFunc i1 i2 b = if b then Just (i1,i2) else Nothing
И затем я использую это как таковое в GHCi:
> appFunc <$> Just 3 <*> Nothing <*> Just True
Nothing
Это здорово, потому что если хотя бы один из параметров равен Nothing
, то все выражение оценивается как Nothing
. Однако, когда все параметры равны Just
, я получаю вложенный Maybe
:
> appFunc <$> Just 3 <*> Just 1 <*> Just False
Just Nothing
В идеале я хотел бы, чтобы он оценивался как старый добрый Nothing
. Поэтому моим решением было использовать join
:
> join $ appFunc <$> Just 3 <*> Just 1 <*> Just True
Just (3,1)
Есть ли лучшее решение или более чистый стиль? Я экспериментировал с функцией монады >>=
, но безуспешно. Например, я пробовал писать:
> Just True >>= appFunc <$> Just 3 <*> Just 1
* Couldn't match expected type `Bool -> Maybe b'
with actual type `Maybe (Bool -> Maybe (Integer, Integer))'
* Possible cause: `(<*>)' is applied to too many arguments
In the second argument of `(>>=)', namely
`appFunc <$> Just 5 <*> Just 4'
In the expression: Just True >>= appFunc <$> Just 5 <*> Just 4
In an equation for `it':
it = Just True >>= appFunc <$> Just 5 <*> Just 4
* Relevant bindings include
it :: Maybe b (bound at <interactive>:51:1)
Эта ошибка имеет смысл для меня, потому что:
appFunc <$> Just 3 <*> Just 1 :: m (a -> m b)
тогда как >>= :: m a -> (a -> m b) -> m b
Есть ли монадное решение или мне просто придерживаться аппликативного стиля с join
?
do
было большим идиоматичным моментом AHA! 20.10.2018