Search code examples
haskelltypeclass

Function to ensure your value is wrapped in a Maybe


I'd like a function that takes an argument and gives back a Maybe value. If the argument has type Maybe a, the implementation should be id, and if the argument is anything else, the implementation should be Just. Surely the right way to do this is with a typeclass, but I'm struggling to get it right. Any suggestions?

main :: IO ()
main = do
    print $ toMaybe 3         -- should be `Just 3`
    print $ toMaybe (Just 3)  -- should be `Just 3` also

I feel like this is probably trivial if I know the right language pragmas or something, but I don't.


Solution

  • You'll need TypeFamilies, and will probably want DerivingVia+StandaloneDeriving+UndecidableInstances.

    class Wrap a where
        type Wrapped a
        wrap :: a -> Wrapped a
    
    instance Wrap (Maybe a) where
        type Wrapped (Maybe a) = Maybe a
        wrap = id
    
    -- choice 1: only TypeFamilies
    instance Wrap Int where
        type Wrapped Int = Maybe Int
        wrap = Just
    
    instance Wrap Bool where
        type Wrapped Bool = Maybe Bool
        wrap = Just
    
    instance Wrapped () where
        type Wrapped () = Maybe ()
        wrap = Just
    
    -- etc. etc.
    
    -- choice 2: we love extensions, turn them all on why not
    newtype UseJust a = UseJust a
    instance Wrap (UseJust a) where
        type Wrapped (UseJust a) = Maybe a
        wrap (UseJust a) = Just a
    
    deriving via UseJust Int instance Wrap Int
    deriving via UseJust Bool instance Wrap Bool
    deriving via UseJust () instance Wrap ()
    -- etc. etc.
    

    And I'll just add a slight warning: to me, this smells. Are you sure you aren't just looking for the Monad (well, Functor) instance for Maybe? If not, are you double-plus sure that two layers of Maybe really isn't conceptually the right thing to return when presented with a single layer of Maybe?