Skip to content

Instantly share code, notes, and snippets.

@carymrobbins
Created July 18, 2018 17:51
Show Gist options
  • Save carymrobbins/3e6dc3301bdeeb9f3fa913c282140460 to your computer and use it in GitHub Desktop.
Save carymrobbins/3e6dc3301bdeeb9f3fa913c282140460 to your computer and use it in GitHub Desktop.
Zero cost dirty subtypes for Haskell
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Main where
import Unsafe.Coerce
main :: IO ()
main = do
let wolf = Wolf "snarl" "branch" "ahoooo!"
putStrLn $ speak wolf
speak :: a <: Animal => a -> String
speak a = animalSpeak $ upcast a
class a <: b | a -> b
instance {-# OVERLAPPABLE #-} forall a b c. (b <: c, a <: b) => a <: c
upcast :: a <: b => a -> b
upcast = unsafeCoerce
data Animal = Animal { animalSpeak :: String }
data Cat = Cat { catSpeak :: String, catHack :: String }
instance Cat <: Animal
data Dog = Dog { dogSpeak :: String, dogFetch :: String }
instance Dog <: Animal
data Wolf = Wolf { wolfSpeak :: String, wolfFetch :: String, wolfHowl :: String }
instance Wolf <: Dog
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment