Skip to content

Instantly share code, notes, and snippets.

@Profpatsch
Created April 22, 2018 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Profpatsch/e7d98c6c2cbc788a84682f670da8cef0 to your computer and use it in GitHub Desktop.
Save Profpatsch/e7d98c6c2cbc788a84682f670da8cef0 to your computer and use it in GitHub Desktop.
Enrich any type class with new methods without depending OrphanInstances
{-# LANGUAGE FlexibleInstances #-}
module Main where
import Data.Monoid
-- This definition would be in another module
class Monoid a => Group a where
inverse :: a -> a
newtype Enrich with a =
Enrich { unrich :: with -> a }
newtype Inv a = Inv (a -> a)
type AsGroup a = Enrich (Inv a) a
-- TODO: use DerivingVia
instance (Monoid a) => Monoid (AsGroup a) where
mempty = Enrich $ const mempty
mappend a b = Enrich
$ \inv -> mappend (unrich a inv) (unrich b inv)
-- No OrphanInstances is needed to instantiate
instance Monoid a => Group (AsGroup a) where
inverse a = Enrich $ \(Inv f) -> f (unrich a (Inv f))
asGroup :: Monoid m => m -> AsGroup m
asGroup m = Enrich $ const m
main = print $
getSum $ unrich (inverse (asGroup $ Sum 4)
`mappend` (asGroup $ Sum 5))
(Inv $ \x -> (-x))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment