Skip to content

Instantly share code, notes, and snippets.

@nebuta
Created September 19, 2013 07:56
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 nebuta/6620334 to your computer and use it in GitHub Desktop.
Save nebuta/6620334 to your computer and use it in GitHub Desktop.
Example of Category instance?
{-# LANGUAGE OverloadedStrings, GADTs, NoImplicitPrelude #-}
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Control.Monad.Writer
import Prelude hiding ((.),id)
import Control.Category
class Reifiable a where
reify :: a -> Text
type FuncName = Text
data Chain a b where
Func :: (a -> b) -> Chain a b
Func' :: FuncName -> Chain a b
Chain :: Chain a c -> Chain c b -> Chain a b
ChainEnd :: Chain a a
-- the code below can't be typed, because ChainEnd cannot be typed as Chain a a without GADTs.
-- data Chain a b = forall c. Chain (a -> c) (Chain c b) | ChainEnd
instance Category Chain where
id = ChainEnd
(.) = flip Chain
-- |evalChain chain1 2 == "6"
chain1 :: Chain Int String
chain1 = Chain (Func (\k -> [k,k,k])) (Chain (Func (show .sum)) ChainEnd)
-- |evalChain chain1' 2 == "6"
chain1' = Func (show . sum) . Func (\k -> [k,k,k])
-- |reify chain2 = "cos().sin()"
chain2 = Func' "sin" . Func' "cos"
evalChain :: Chain a b -> a -> b
evalChain (Chain (Func f) rest) a = evalChain rest (f a)
evalChain ChainEnd a = a
evalChain (Func f) a = f a
instance Reifiable (Chain a b) where
reify (Chain f ChainEnd) = T.concat [reify f]
reify (Chain f g) = T.concat [reify f,".",reify g]
reify (Func f) = "someFunc()"
reify (Func' name) = T.concat [name,"()"]
reify ChainEnd = ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment