Need help with (untyped ?) / heterogeneous dictionary as context to template
Hello
From https://github.com/tdammers/ginger/blob/master/doc/getting-started.markdown#running---the-easy-interface
Note that, because Ginger is a dynamically typed language (or, actually, an untyped language), passing values to a template execution context requires conversion to Ginger values, represented on the Haskell side as the GVal type. The ToGVal typeclass exposes a number of convenience functions that can be used for this purpose, and there are instances for many of Haskell's standard data types.
I wanted to model a dictionary with different types of values. When i adapt the easyRender example in the manual it gets really complicated (for me personally it was anyway).
Here is the changed code with the type errors it yields: >>> CODE <<<
context :: HashMap Text (GVal (Run SourcePos (Writer Text) Text))
context = HashMap.fromList
[ ("name", toGVal ("Alice" :: Text))
, ("location", toGVal ("Wonderland" :: String))
, ("age", toGVal (155 :: Int))
]
Maybe this could be the right type ?? It typechecked on this level but still throw another type error near easyRender
Proposed was the following patch:
-- This would work with the patch below
context :: HashMap Text (GVal m)
context = HashMap.fromList
[ ("name", toGVal ("Alice" :: Text))
, ("location", toGVal ("Wonderland" :: String))
, ("age", toGVal (155 :: Int))
]
{-
--- ginger-0.10.1.0/src/Text/Ginger/GVal.hs 2001-09-09 03:46:40.000000000 +0200
+++ ginger-0.10.1.0-my/src/Text/Ginger/GVal.hs 2020-09-02 10:10:21.853396692 +0200
@@ -3,6 +3,7 @@
{-#LANGUAGE FlexibleInstances #-}
{-#LANGUAGE ScopedTypeVariables #-}
{-#LANGUAGE RankNTypes #-}
+{-#LANGUAGE TypeFamilies #-}
-- | GVal is a generic unitype value, representing the kind of values that
-- Ginger can understand.
@@ -314,7 +315,7 @@
toGVal :: a -> GVal m
-- | Trivial instance for 'GVal' itself.
-instance ToGVal m (GVal m) where
+instance (m ~ m') => ToGVal m (GVal m') where
toGVal = id
instance ToGVal m () where
-}
Supposingly the code could then look like this
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
-- ...
newtype GVal' m = GVal' { unGVal' :: GVal m }
toGVal' v = GVal' (toGVal v)
instance (m ~ m') => ToGVal m (GVal' m') where
toGVal = unGVal'
context :: HashMap Text (GVal' m)
context = HashMap.fromList
[ ("name", toGVal' ("Alice" :: Text))
, ("location", toGVal' ("Wonderland" :: String))
, ("age", toGVal' (155 :: Int))
]
I didn't look if this patch makes sense but it seemed a very helpful suggestion.
For me the documentation is not clear about how to handle this scenario. I think it's quite common to have a dictionary with different types. Think of person with age int and name string. Maybe also something in ginger can be changed to simplify types or instances, i don't know.
Other than this it looks like a really nice package, i'm eager to get my first template working :)