Skip to content

Instantly share code, notes, and snippets.

@pjrt
Last active July 26, 2018 08:55
Show Gist options
  • Select an option

  • Save pjrt/3b2231e323f5a557ebea to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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