Skip to content

Instantly share code, notes, and snippets.

@sirlensalot
Last active January 6, 2016 22:43
Show Gist options
  • Save sirlensalot/3132a7597e1caa9afad4 to your computer and use it in GitHub Desktop.
Save sirlensalot/3132a7597e1caa9afad4 to your computer and use it in GitHub Desktop.
Transforming classy stuff.
-- Transforming between classy stuff.
-- | Foo is present in input and output.
data Foo = Foo
-- | Classy.
class HasFoo a where foo :: Lens' a Foo
-- | Maybe Bar is added to output type.
data Bar = Bar
-- | Classy.
class HasBar a where bar :: Lens' a Bar
-- | The nicest way would automagically coerce to the result type, but
-- can't figure out how that would happen.
addBarNicest :: (Traversable t, HasFoo a, HasFoo b, HasBar b) => t a -> t b
addBarNicest = undefined -- ???? no way to instantiate the caller's choice of b
-- | More "manual", provide a transformer function.
addBarTxf :: (Traversable t, HasFoo a, HasFoo b, HasBar b) => (a -> b) -> t a -> t b
addBarTxf f = fmap (set bar Bar . f)
-- | Lensy, provide an Iso.
addBarIso :: (Traversable t, HasFoo a, HasFoo b, HasBar b) => Iso' a b -> t a -> t b
addBarIso i = fmap (set bar Bar . view i)
-- | Define a class that specifies the type change.
-- This could perhaps be part of 'HasFoo', too -- 'WithFoo' with lens and iso-ish thingy.
class FromFoo a where
fromFoo :: HasFoo b => b -> a
addBarFrom :: (Traversable t, HasFoo a, HasFoo b, HasBar b, FromFoo b) => t a -> t b
addBarFrom = fmap (set bar Bar . fromFoo)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment