Skip to content

Instantly share code, notes, and snippets.

@llelf
Forked from sjoerdvisscher/liftedMonoid.hs
Created May 3, 2018 04:51
Show Gist options
  • Save llelf/804b80b717e19749594108ef03af4a48 to your computer and use it in GitHub Desktop.
Save llelf/804b80b717e19749594108ef03af4a48 to your computer and use it in GitHub Desktop.
If you have a Functor f with an instance Monoid a => Monoid (f a), f is Applicative!
{-# LANGUAGE TypeOperators, ScopedTypeVariables, TupleSections #-}
import Data.Constraint
import Data.Monoid
import Control.Applicative
pureDefault :: forall f a. Functor f
=> (Monoid () :- Monoid (f ()))
-> a -> f a
pureDefault (Sub Dict) a = a <$ (mempty :: f ())
apDefault :: forall f a b. Functor f
=> (Monoid (First (a -> b), First a) :- Monoid (f (First (a -> b), First a)))
-> f (a -> b) -> f a -> f b
apDefault (Sub Dict) fab fa = fmap (\(First (Just f), First (Just a)) -> f a) $
fmap (\f -> (First (Just f), mempty)) fab `mappend` fmap (\a -> (mempty, First (Just a))) fa
-- Example (Dual is just the identity applicative)
pfDual :: Monoid a :- Monoid (Dual a)
pfDual = Sub Dict
instance Functor Dual where
fmap f (Dual a) = Dual (f a)
instance Applicative Dual where
pure = pureDefault pfDual
(<*>) = apDefault pfDual
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment