{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} module Interpreter.Rep where import Data.IORef import GHC.TypeError import Array import AST type family Rep t where Rep TNil = () Rep (TPair a b) = (Rep a, Rep b) Rep (TEither a b) = Either (Rep a) (Rep b) Rep (TMaybe t) = Maybe (Rep t) Rep (TArr n t) = Array n (Rep t) Rep (TScal sty) = ScalRep sty Rep (TAccum t) = RepAcSparse t -- Mutable, and has a zero. The zero may not be O(1), but RepAcSparse (D2 t) will have an O(1) zero. type family RepAcSparse t where RepAcSparse TNil = () RepAcSparse (TPair a b) = IORef (RepAcSparse a, RepAcSparse b) RepAcSparse (TEither a b) = TypeError (Text "Non-sparse coproduct is not a monoid") RepAcSparse (TMaybe t) = IORef (Maybe (RepAcDense t)) -- allow the value to be dense, because the Maybe's zero can be used for the contents RepAcSparse (TArr n t) = IORef (Array n (RepAcSparse t)) -- empty array is zero RepAcSparse (TScal sty) = IORef (ScalRep sty) RepAcSparse (TAccum t) = TypeError (Text "RepAcSparse: Nested accumulators") -- Immutable, and does not necessarily have a zero. type family RepAcDense t where RepAcDense TNil = () -- RepAcDense (TPair a b) = (RepAcSparse a, RepAcSparse b) RepAcDense (TEither a b) = Either (RepAcSparse a) (RepAcSparse b) -- RepAcDense (TMaybe t) = RepAcSparse (TMaybe t) -- ^ This can be optimised to TMaybe (RepAcSparse t), but that makes accumAddDense very hard to write. And in any case, we don't need it because D2 will not produce Maybe of Maybe. -- RepAcDense (TArr n t) = Array n (RepAcSparse t) -- RepAcDense (TScal sty) = ScalRep sty -- RepAcDense (TAccum t) = TypeError (Text "RepAcDense: Nested accumulators")