moleike / haskell-jsonnet

🎏 Haskell implementation of Jsonnet
https://hackage.haskell.org/package/jsonnet
Other
21 stars 6 forks source link

Add hidden field #5

Closed CristhianMotoche closed 4 years ago

CristhianMotoche commented 4 years ago

Solves #2

Changes

Please, let me know if this would solve the issue. :smiley:

moleike commented 4 years ago

Hi Cristhian, thanks for your patch! I am reviewing this later πŸ‘

CristhianMotoche commented 4 years ago

Thanks for the suggestions @moleike I'll review them later today.

CristhianMotoche commented 4 years ago

Hi @moleike I tried your approach but I got stuck with this type error:

...l/jsonnet-haskell/src/Language/Jsonnet/Std.hs:42:26: error:
    β€’ No instance for (Integral Key) arising from a use of β€˜inj’
    β€’ In the expression: inj (H.keys @Key @Value)
      In the expression: ("objectFields", inj (H.keys @Key @Value))
      In the expression:
        [("assertEqual", inj assertEqual), ("type", inj valueType),
         ("isString", inj (isType "string")),
         ("isBoolean", inj (isType "boolean")), ....]
   |
42 |         ("objectFields", inj (H.keys @Key @Value)),

Please, let me know if I'm going in the right direction or I lost at some point. I understood that manifest makes the final conversion of Value to JSON and it's used in toString and equalTo. Therefore, I should filter the visible keys there.

CristhianMotoche commented 4 years ago

I managed to fix the error type, but I'm not sure about my implementation.

moleike commented 4 years ago

Hi @CristhianMotoche, the problem you encounter is due to the impl. of objectFields method. So you don't need an HasValue instance for Key:

diff --git a/src/Language/Jsonnet/Eval.hs b/src/Language/Jsonnet/Eval.hs
index 8dc0428..d0c0993 100644
--- a/src/Language/Jsonnet/Eval.hs
+++ b/src/Language/Jsonnet/Eval.hs
@@ -124,10 +124,6 @@ instance HasValue Double where
   proj v = throwTypeMismatch "number" v
   inj = VNum

-instance HasValue Key where
-  proj = undefined
-  inj = undefined
-
 instance {-# OVERLAPS #-} Integral a => HasValue a where
   proj (VNum n) = pure (round n)
   proj v = throwTypeMismatch "number" v
diff --git a/src/Language/Jsonnet/Std.hs b/src/Language/Jsonnet/Std.hs
index ba2a1d3..2f8d67a 100644
--- a/src/Language/Jsonnet/Std.hs
+++ b/src/Language/Jsonnet/Std.hs
@@ -9,6 +9,7 @@ import Control.Applicative
 import Control.Monad.Except
 import qualified Data.ByteString as B
 import Data.Foldable
+import Data.HashMap.Lazy (HashMap)
 import qualified Data.HashMap.Lazy as H
 import Data.List
 import Data.Text (Text)
@@ -39,7 +40,7 @@ std = VObj $ (Thunk . pure) <$> H.fromList (map (\(k, v) -> (Visible k, v)) xs)
         ("isObject", inj (isType "object")),
         ("isArray", inj (isType "array")),
         ("isFunction", inj (isType "function")),
-        ("objectFields", inj (H.keys @Key @Value)),
+        ("objectFields", inj objectFields),
         ("length", inj length'),
         ("abs", inj (abs @Double)),
         ("sign", inj (signum @Double)), -- incl. 0.0, (-0.0), and NaN
@@ -98,6 +99,10 @@ std = VObj $ (Thunk . pure) <$> H.fromList (map (\(k, v) -> (Visible k, v)) xs)
         ("reverse", inj (reverse @Value))
       ]

+
+objectFields :: HashMap Key Value -> [Text]
+objectFields o = [k | Visible k <- H.keys o]
+
 assertEqual :: Value -> Value -> Eval Bool
 assertEqual a b = do
   a' <- manifest a
moleike commented 4 years ago

I understood that manifest makes the final conversion of Value to JSON and it's used in toString and equalTo. Therefore, I should filter the visible keys there.

That's correct.

Please, let me know if I'm going in the right direction

Yes you are πŸ‘

CristhianMotoche commented 4 years ago

Thank you so much for you kind guidance @moleike Let me know if you have any other comment/suggestion. :smiley:

moleike commented 4 years ago

@CristhianMotoche I think the issue is solved with your changes. Congrats on tackling this issue!

moleike commented 4 years ago

There's one minor issue remaining, but it can be fixed later on: The parses will fail to parse { foo(x) :: x }, which is sugar for { foo :: function(x) x }.