{-#LANGUAGE FlexibleInstances, UndecidableInstances, IncoherentInstances #-} module Data.Variant.ToFrom where import Data.Variant import Prelude hiding (toInteger) class ToVariant a where toVariant :: a -> Variant class FromVariant a where fromVariant :: Variant -> a -- Variant itself implements to/from variant instance ToVariant Variant where toVariant = id instance FromVariant Variant where fromVariant = id -- Various scalar instances instance ToVariant String where toVariant = String instance FromVariant String where fromVariant = flatten instance ToVariant Bool where toVariant = Bool instance FromVariant Bool where fromVariant = toBool instance ToVariant Double where toVariant = Double instance FromVariant Double where fromVariant = toDouble instance ToVariant Integer where toVariant = Integer instance FromVariant Integer where fromVariant = toInteger instance ToVariant Int where toVariant = Integer . fromIntegral instance FromVariant Int where fromVariant = fromIntegral . toInteger -- Maybes of to/from variant types implement to/from variant instance ToVariant a => ToVariant (Maybe a) where toVariant Nothing = Null toVariant (Just a) = toVariant a instance FromVariant a => FromVariant (Maybe a) where fromVariant Null = Nothing fromVariant a = Just (fromVariant a) -- Lists of variants instance (ToVariant a, ToVariant b) => ToVariant [(a,b)] where toVariant xs = let (keys, values) = unzip xs vkeys = map toVariant keys vvalues = map toVariant values in AList $ zip vkeys vvalues instance (FromVariant a, FromVariant b) => FromVariant [(a,b)] where fromVariant = map (\(k,v) -> (fromVariant k, fromVariant v)) . toAList instance ToVariant a => ToVariant [a] where toVariant xs = List (map toVariant xs) instance FromVariant a => FromVariant [a] where fromVariant = map fromVariant . values -- Functions, up to 3 arguments instance (FromVariant a, ToVariant b) => ToVariant (a -> b) where toVariant f = Function (\(x:_) -> toVariant (f $ fromVariant x)) instance (FromVariant a, FromVariant b, ToVariant c) => ToVariant (a -> b -> c) where toVariant f = Function (\(x:y:_) -> toVariant (f (fromVariant x) (fromVariant y))) instance (FromVariant a, FromVariant b, FromVariant c, ToVariant d) => ToVariant (a -> b -> c -> d) where toVariant f = Function (\(x:y:z:_) -> toVariant (f (fromVariant x) (fromVariant y) (fromVariant z)))