Skip to content

Instantly share code, notes, and snippets.

@pjrt
Last active July 26, 2018 08:55
Show Gist options
  • Save pjrt/3b2231e323f5a557ebea to your computer and use it in GitHub Desktop.
Save pjrt/3b2231e323f5a557ebea to your computer and use it in GitHub Desktop.
A Typeclass Box in Haskell. Allows for a single type to represent any type that responds to a typeclass.
{-# LANGUAGE GADTs, ConstraintKinds, FlexibleInstances, RankNTypes #-}
-- Our typeclass with a simple foo :: a -> String func
class Foo a where
foo :: a -> String
-- Our test data types and their instances of Foo
data MyFoo = MyFoo String
data MyBar = MyBar Int
instance Foo MyFoo where
foo (MyFoo s) = s
instance Foo MyBar where
foo (MyBar i) = show i
-- Our Typeclass Box (TBox). Needs GADTs. `a` is existential. `c` is a contraint
data TBox c where
TBox :: c a => a -> TBox c
-- A TBox can be represented as a Foo (it is whatever its inner representation of Foo is).
-- Notice that `a` is existential. We don't know what it is, we just know that we can call `foo` on it.
-- Needs FlexibleInstances.
instance Foo (TBox Foo) where
foo (TBox a) = foo a
main = do
-- We can now make a list of TBox where each inner type is different
let listOfFoo = (TBox (MyFoo "hello") : TBox (MyBar 123) : []) :: [TBox Foo]
-- AND we can call `foo` on all of them via map
mapM_ putStrLn $ fmap foo listOfFoo
@Globidev
Copy link

Globidev commented Jul 2, 2018

Thank you for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment