{-# LANGUAGE ConstraintKinds, RankNTypes, GADTs, TypeFamilies #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
{-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
module Build.Task.Typed (Task, Key (..), showDependencies) where
import Data.Functor.Const
import Data.Functor.Identity
class Key k where
type Value k :: *
showKey :: k -> String
type Task c k = forall f. c f => (forall k. Key k => k -> f (Value k)) -> k -> Maybe (f (Value k))
showDependencies :: Task Applicative k -> k -> [String]
showDependencies task = maybe [] getConst . task (\k -> Const [showKey k])
data ExampleKey a where
Base :: ExampleKey Int
Number :: ExampleKey Int
SplitDigit :: ExampleKey (Int, Int)
LastDigit :: ExampleKey Int
BaseDigits :: ExampleKey [Int]
instance Show (ExampleKey a) where
show key = case key of
Base -> "Base"
Number -> "Number"
SplitDigit -> "SplitDigit"
LastDigit -> "LastDigit"
BaseDigits -> "BaseDigits"
instance Key (ExampleKey a) where
type Value (ExampleKey a) = a
showKey = show
digits :: Task Applicative (ExampleKey a)
digits fetch SplitDigit = Just $ divMod <$> fetch Number <*> fetch Base
digits fetch LastDigit = Just $ snd <$> fetch SplitDigit
digits fetch BaseDigits = Just $ enumFromTo 1 <$> fetch Base
digits _ _ = Nothing
fetch :: ExampleKey t -> Identity (Value (ExampleKey t))
fetch key = Identity $ case key of
Base -> 10
Number -> 2018
SplitDigit -> (201, 8)
LastDigit -> 8
BaseDigits -> [0..9]