Skip to content

Instantly share code, notes, and snippets.

@treeowl

treeowl/Gen.hs Secret

Created June 16, 2017 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save treeowl/ca72b86ea4593e784e61b03ff28e26c7 to your computer and use it in GitHub Desktop.
Save treeowl/ca72b86ea4593e784e61b03ff28e26c7 to your computer and use it in GitHub Desktop.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
module Gen where
import GHC.Generics
import Control.Monad
import Control.Applicative
import Data.Monoid
data PairS a = PairS a !(() -> ())
newtype PutM a = Put { unPut :: PairS a }
-- Use of this writer monad seems to be important; IO speeds it up
type Put = PutM ()
--type Put = IO ()
-- binary has INLINE pragmas on most of the instances but you can still
-- trigger bad behavior without them.
instance Functor PutM where
fmap f m = Put $ let PairS a w = unPut m in PairS (f a) w
-- Just to appease AMP
instance Applicative PutM where
pure = return
(<*>) = ap
instance Monad PutM where
return a = Put $ PairS a id
m >>= k = Put $
let PairS a w = unPut m
PairS b w' = unPut (k a)
in PairS b (w . w')
class GBinary f where
gput :: f t -> Put
-- Forcing the dictionary to have two elements hurts
-- the optimizer a lot.
not_used :: f t
instance GBinary a => GBinary (M1 i c a) where
gput = gput . unM1
instance Binary a => GBinary (K1 i a) where
gput = put . unK1
instance (GBinary a, GBinary b) => GBinary (a :*: b) where
gput (x :*: y) = gput x >> gput y
class Binary t where
put :: t -> Put
instance Binary () where
put () = return ()
data T = T () () () () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
() () () () () () () () () ()
deriving Generic
module GenSpec where
import Gen
import GHC.Generics
-- Trigger specialization
tput :: T -> Put
tput = gput . from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment