module Elm.Type where
import Data.Int (Int16, Int32, Int64, Int8)
import Data.IntMap
import Data.Map
import Data.Proxy
import Data.Text
import Data.Time
import GHC.Generics
import Prelude
data ElmDatatype
= ElmDatatype Text
ElmConstructor
| ElmPrimitive ElmPrimitive
deriving (Show, Eq)
data ElmPrimitive
= EInt
| EBool
| EChar
| EDate
| EFloat
| EString
| EUnit
| EList ElmDatatype
| EMaybe ElmDatatype
| ETuple2 ElmDatatype
ElmDatatype
| EDict ElmPrimitive
ElmDatatype
deriving (Show, Eq)
data ElmConstructor
= NamedConstructor Text
ElmValue
| RecordConstructor Text
ElmValue
| MultipleConstructors [ElmConstructor]
deriving (Show, Eq)
data ElmValue
= ElmRef Text
| ElmEmpty
| ElmPrimitiveRef ElmPrimitive
| Values ElmValue
ElmValue
| ElmField Text
ElmValue
deriving (Show, Eq)
class ElmType a where
toElmType :: a -> ElmDatatype
toElmType = genericToElmDatatype . from
default toElmType :: (Generic a, GenericElmDatatype (Rep a)) =>
a -> ElmDatatype
class GenericElmDatatype f where
genericToElmDatatype :: f a -> ElmDatatype
instance (Datatype d, GenericElmConstructor f) =>
GenericElmDatatype (D1 d f) where
genericToElmDatatype datatype =
ElmDatatype
(pack (datatypeName datatype))
(genericToElmConstructor (unM1 datatype))
class GenericElmConstructor f where
genericToElmConstructor :: f a -> ElmConstructor
instance (Constructor c, GenericElmValue f) =>
GenericElmConstructor (C1 c f) where
genericToElmConstructor constructor =
if conIsRecord constructor
then RecordConstructor name (genericToElmValue (unM1 constructor))
else NamedConstructor name (genericToElmValue (unM1 constructor))
where
name = pack $ conName constructor
instance (GenericElmConstructor f, GenericElmConstructor g) =>
GenericElmConstructor (f :+: g) where
genericToElmConstructor _ =
MultipleConstructors
[ genericToElmConstructor (undefined :: f p)
, genericToElmConstructor (undefined :: g p)
]
class GenericElmValue f where
genericToElmValue :: f a -> ElmValue
instance (Selector s, GenericElmValue a) =>
GenericElmValue (S1 s a) where
genericToElmValue selector =
case selName selector of
"" -> genericToElmValue (undefined :: a p)
name -> ElmField (pack name) (genericToElmValue (undefined :: a p))
instance (GenericElmValue f, GenericElmValue g) =>
GenericElmValue (f :*: g) where
genericToElmValue _ =
Values
(genericToElmValue (undefined :: f p))
(genericToElmValue (undefined :: g p))
instance GenericElmValue U1 where
genericToElmValue _ = ElmEmpty
instance ElmType a =>
GenericElmValue (Rec0 a) where
genericToElmValue _ =
case toElmType (Proxy :: Proxy a) of
ElmPrimitive primitive -> ElmPrimitiveRef primitive
ElmDatatype name _ -> ElmRef name
instance ElmType a =>
ElmType [a] where
toElmType _ = ElmPrimitive (EList (toElmType (Proxy :: Proxy a)))
instance ElmType a =>
ElmType (Maybe a) where
toElmType _ = ElmPrimitive (EMaybe (toElmType (Proxy :: Proxy a)))
instance ElmType () where
toElmType _ = ElmPrimitive EUnit
instance ElmType Text where
toElmType _ = ElmPrimitive EString
instance ElmType Day where
toElmType _ = ElmPrimitive EDate
instance ElmType UTCTime where
toElmType _ = ElmPrimitive EDate
instance ElmType Float where
toElmType _ = ElmPrimitive EFloat
instance ElmType Double where
toElmType _ = ElmPrimitive EFloat
instance ElmType Int8 where
toElmType _ = ElmPrimitive EInt
instance ElmType Int16 where
toElmType _ = ElmPrimitive EInt
instance ElmType Int32 where
toElmType _ = ElmPrimitive EInt
instance ElmType Int64 where
toElmType _ = ElmPrimitive EInt
instance (ElmType a, ElmType b) =>
ElmType (a, b) where
toElmType _ =
ElmPrimitive $
ETuple2 (toElmType (Proxy :: Proxy a)) (toElmType (Proxy :: Proxy b))
instance (ElmType a) =>
ElmType (Proxy a) where
toElmType _ = toElmType (undefined :: a)
instance (HasElmComparable k, ElmType v) =>
ElmType (Map k v) where
toElmType _ =
ElmPrimitive $
EDict (toElmComparable (undefined :: k)) (toElmType (Proxy :: Proxy v))
instance (ElmType v) =>
ElmType (IntMap v) where
toElmType _ = ElmPrimitive $ EDict EInt (toElmType (Proxy :: Proxy v))
class HasElmComparable a where
toElmComparable :: a -> ElmPrimitive
instance HasElmComparable String where
toElmComparable _ = EString
instance ElmType Int where
toElmType _ = ElmPrimitive EInt
instance ElmType Char where
toElmType _ = ElmPrimitive EChar
instance ElmType Bool where
toElmType _ = ElmPrimitive EBool