Is there anyway to trick haskell (raw haskell ? source plugins ? anything ?) to get a proof tree of how a type class was derived ?
What I would like, says using the exemple below :
**Diff**
-- --
Id Id
---- ----------
Unit Prod Id Id
---------------------
Sum Unit (Prod Id Id)
#!/usr/bin/env stack
-- stack --resolver lts-17.10 script
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE EmptyDataDeriving #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnicodeSyntax #-}
module SOShow where
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
import Data.Constraint
import Data.Typeable
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- universe of polynomial functors
data Zero a deriving (Show)
data Unit a = Unit deriving (Show)
data Id a = Id a deriving (Show)
data Sum s t a = Inl (s a) | Inr (t a) deriving (Show)
data Prod s t a = s a :*: t a deriving (Show)
magic :: Zero a -> b
magic z = seq z (error "This is magic")
instance Functor Unit where fmap f z = Unit
instance Functor Id where fmap f (Id a) = Id (f a)
instance (Functor s, Functor t) => Functor (Sum s t) where
fmap f s = case s of (Inl s) -> Inl (fmap f s); (Inr s) -> Inr (fmap f s)
instance (Functor s, Functor t) => Functor (Prod s t) where fmap f (s :*: t) = fmap f s :*: fmap f t
-- TreeF
type TreeF = Sum Unit (Prod Id Id)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Derivatives
class Functor f => Diff f where
type Δ f :: * -> *
posns :: f a -> f (a, Δ f a)
plug :: (a, Δ f a) -> f a
instance Diff Unit where
type Δ Unit = Zero
posns Unit = Unit
plug (a, z) = magic z
instance Diff Id where
type Δ Id = Unit
posns (Id a) = Id (a, Unit)
plug (a, Unit) = Id a
instance (Diff f, Diff g) => Diff (Sum f g) where
type Δ (Sum f g) = Sum (Δ f) (Δ g)
posns (Inl (x :: f a)) = Inl (fmap (\(a, dx) -> (a, Inl dx)) (posns x :: f (a, Δ f a)))
posns (Inr y) = Inr (fmap (\(a, dy) -> (a, Inr dy)) (posns y))
plug (a, Inl (x :: Δ f a)) = Inl (plug (a, x) :: f a)
plug (a, Inr y) = Inr (plug (a, y))
instance (Diff f, Diff g) => Diff (Prod f g) where
type Δ (Prod f g) = Sum (Prod (Δ f) g) (Prod f (Δ g))
posns (x :*: y) = fmap (\(a, dx) -> (a, Inl (dx :*: y))) (posns x) :*: fmap (\(a, dy) -> (a, Inr (x :*: dy))) (posns y)
plug (a, Inl (dx :*: y)) = plug (a, dx) :*: y
plug (a, Inr (x :*: dy)) = x :*: plug (a, dy)
type B = Δ TreeF
-- > :k! B
-- B :: * -> *
-- = Sum Zero (Sum (Prod Unit Id) (Prod Id Unit))
w :: Dict (Diff TreeF) = Dict
main :: IO ()
main = do
print w --Dict
print (typeOf w) -- Dict (Diff (Sum Unit (Prod Id Id)))
{-
**Diff**
-- --
Id Id
---- ----------
Unit Prod Id Id
---------------------
Sum Unit (Prod Id Id)
-}