Что является обратной стороной fmap? - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть цепочка функторов, и мне нужно в какой-то момент свернуть мое значение в Maybe:

module Funct where 
(>>?) :: Maybe a -> (a -> Maybe b) -> Maybe b
(Just a) >>? f = f a
Nothing >>? _ = Nothing


f1 :: Int -> Maybe Bool
f1 a = if a > 2 then Just (a `mod` 2 == 0)  else Nothing

f2 :: Bool ->  Char
f2 b = if b then 'a' else 'b'

f3 :: Char -> Maybe Int
f3 c = if c == 'a' then Just 1 else Nothing

fm :: Int -> Maybe Int
fm x = f1 x >>? f2  >>? f3
                 ^ 
                 Is there a reverse method for fmap particular for Maybe 
                 or do I have to implement it?

Реализован

myWrapper :: Char->Maybe Char
myWrapper c = Just c

fm x = f1 x >>? myWrapper . f2 >>? f3  -- is there any built in way more concise?

Я спрашиваю, потому что при цепочке, я полагаю, вам понадобятся обертки для других монад, например Either.

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

(<&>) = flip fmap имеет тот же приоритет, что и (>>=):

fm x = f1 x <&> f2 >>= f3
0 голосов
/ 01 ноября 2018

Я спрашиваю, потому что при цепочке, я полагаю, вам понадобятся обертки для других монад, таких как Either.

Правильно. Каждый конструктор типов, такой как Maybe и Either, нуждается в своем собственном определении для таких вещей, как >>= и return, но это именно то, чем является экземпляр класса типов: определения методов класса типов, специализированные для конкретного конструктора типов. Например,

class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b

instance Monad Maybe where
    return = Just
    Nothing >>= _ = Nothing
    (Just x) >>= f = f x

-- This looks similar to the Maybe instance because in some sense,
-- Maybe is just a special case of Either: Maybe ~ Either ()
instance Monad (Either a) where
    return = Right
    (Left x) >>= _ = Left x
    (Right x) >>= f = f x

Ваша функция fm может быть написана так, чтобы она работала для любой монады, а не только Maybe:

fm :: Maybe m => Int -> m Int
fm x = f1 x >>= return . f2  >>= f3
0 голосов
/ 01 ноября 2018

(есть ли какой-нибудь встроенный способ более лаконичный?)

Sure:

myWrapper = Just

или встроенный:

fm x= f1 x>>? Just . f2 >>? f3

Конструкторы данных можно рассматривать как простые функции, так что вы можете создавать их с другими функциями.

...