{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
module Language.Jsonnet.Value where

import Control.Applicative
import Control.Arrow
import Control.Monad.Except
import Control.Monad.IO.Class
import Control.Monad.Reader
import Control.Monad.State.Lazy
import Data.Bits
import Data.ByteString (ByteString)
import Data.Data
import Data.HashMap.Lazy (HashMap)
import qualified Data.HashMap.Lazy as H
import Data.Hashable (Hashable)
import Data.IORef
import Data.Int
import Data.Map.Lazy (Map)
import qualified Data.Map.Lazy as M
import Data.Scientific (Scientific, fromFloatDigits, toRealFloat)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Typeable
import Data.Vector (Vector, (!?))
import qualified Data.Vector as V
import Debug.Trace
import GHC.Generics (Generic)
import Language.Jsonnet.Common
import Language.Jsonnet.Core
import Language.Jsonnet.Error
import {-# SOURCE #-} Language.Jsonnet.Eval (eval, evalClos)
import Language.Jsonnet.Eval.Monad
import Language.Jsonnet.Parser.SrcSpan
import Language.Jsonnet.Pretty ()
import Text.PrettyPrint.ANSI.Leijen (Doc, pretty)
import Unbound.Generics.LocallyNameless

-- jsonnet value
data Value
  = VNull
  | VBool !Bool
  | VNum !Scientific
  | VStr !Text
  | VArr !Array
  | VObj !(HashMap Text (Hideable Thunk))
  | VClos !Fun !Env
  | VFun !(Thunk -> Eval Value)
  deriving ((forall x. Value -> Rep Value x)
-> (forall x. Rep Value x -> Value) -> Generic Value
forall x. Rep Value x -> Value
forall x. Value -> Rep Value x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Value x -> Value
$cfrom :: forall x. Value -> Rep Value x
Generic)

type Array = Vector Thunk

type Object = HashMap Text (Hideable Thunk)

valueType :: Value -> Text
valueType :: Value -> Text
valueType =
  \case
    Value
VNull -> Text
"null"
    VBool Bool
_ -> Text
"boolean"
    VNum Scientific
_ -> Text
"number"
    VStr Text
_ -> Text
"string"
    VArr Array
_ -> Text
"array"
    VObj HashMap Text (Hideable Thunk)
_ -> Text
"object"
    VClos Fun
_ Env
_ -> Text
"function"
    VFun Thunk -> Eval Value
_ -> Text
"function"

data Thunk = TC !Ctx !Core | TV !(Eval Value)
  deriving ((forall x. Thunk -> Rep Thunk x)
-> (forall x. Rep Thunk x -> Thunk) -> Generic Thunk
forall x. Rep Thunk x -> Thunk
forall x. Thunk -> Rep Thunk x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Thunk x -> Thunk
$cfrom :: forall x. Thunk -> Rep Thunk x
Generic)

force :: Thunk -> Eval Value
force :: Thunk -> Eval Value
force = \case
  TC Ctx
rho Core
expr -> Ctx -> Eval Value -> Eval Value
forall a. Ctx -> Eval a -> Eval a
withCtx Ctx
rho (Core -> Eval Value
eval Core
expr)
  TV Eval Value
comp -> Eval Value
comp

mkThunk' :: Value -> Thunk
mkThunk' :: Value -> Thunk
mkThunk' = Eval Value -> Thunk
TV (Eval Value -> Thunk) -> (Value -> Eval Value) -> Value -> Thunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Eval Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure

mkThunk :: MonadIO m => Eval Value -> m Thunk
mkThunk :: forall (m :: * -> *). MonadIO m => Eval Value -> m Thunk
mkThunk Eval Value
ev = do
  IORef (Maybe Value)
ref <- IO (IORef (Maybe Value)) -> m (IORef (Maybe Value))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef (Maybe Value)) -> m (IORef (Maybe Value)))
-> IO (IORef (Maybe Value)) -> m (IORef (Maybe Value))
forall a b. (a -> b) -> a -> b
$ Maybe Value -> IO (IORef (Maybe Value))
forall a. a -> IO (IORef a)
newIORef Maybe Value
forall a. Maybe a
Nothing
  Thunk -> m Thunk
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Thunk -> m Thunk) -> Thunk -> m Thunk
forall a b. (a -> b) -> a -> b
$
    Eval Value -> Thunk
TV (Eval Value -> Thunk) -> Eval Value -> Thunk
forall a b. (a -> b) -> a -> b
$
      IO (Maybe Value) -> Eval (Maybe Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IORef (Maybe Value) -> IO (Maybe Value)
forall a. IORef a -> IO a
readIORef IORef (Maybe Value)
ref) Eval (Maybe Value) -> (Maybe Value -> Eval Value) -> Eval Value
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Maybe Value
Nothing -> do
          Value
v <- Eval Value
ev
          IO () -> Eval ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Eval ()) -> IO () -> Eval ()
forall a b. (a -> b) -> a -> b
$ IORef (Maybe Value) -> Maybe Value -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe Value)
ref (Maybe Value -> IO ()) -> Maybe Value -> IO ()
forall a b. (a -> b) -> a -> b
$ Value -> Maybe Value
forall a. a -> Maybe a
Just Value
v
          Value -> Eval Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
v
        Just Value
v -> Value -> Eval Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
v

proj' :: HasValue a => Thunk -> Eval a
proj' :: forall a. HasValue a => Thunk -> Eval a
proj' = Thunk -> Eval Value
force (Thunk -> Eval Value) -> (Value -> Eval a) -> Thunk -> Eval a
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Value -> Eval a
forall a. HasValue a => Value -> Eval a
proj

class HasValue a where
  proj :: Value -> Eval a
  inj :: a -> Value

instance {-# OVERLAPS #-} HasValue Value where
  proj :: Value -> Eval Value
proj = Value -> Eval Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  inj :: Value -> Value
inj = Value -> Value
forall a. a -> a
id

instance HasValue Bool where
  proj :: Value -> Eval Bool
proj (VBool Bool
n) = Bool -> Eval Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
n
  proj Value
v = Text -> Value -> Eval Bool
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"bool" Value
v
  inj :: Bool -> Value
inj = Bool -> Value
VBool

instance HasValue Text where
  proj :: Value -> Eval Text
proj (VStr Text
s) = Text -> Eval Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
s
  proj Value
v = Text -> Value -> Eval Text
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"string" Value
v
  inj :: Text -> Value
inj = Text -> Value
VStr

instance {-# OVERLAPPING #-} HasValue [Char] where
  proj :: Value -> Eval [Char]
proj (VStr Text
s) = [Char] -> Eval [Char]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Char] -> Eval [Char]) -> [Char] -> Eval [Char]
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
T.unpack Text
s
  proj Value
v = Text -> Value -> Eval [Char]
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"string" Value
v
  inj :: [Char] -> Value
inj = Text -> Value
VStr (Text -> Value) -> ([Char] -> Text) -> [Char] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack

instance HasValue ByteString where
  proj :: Value -> Eval ByteString
proj (VStr Text
s) = ByteString -> Eval ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ByteString
encodeUtf8 Text
s)
  proj Value
v = Text -> Value -> Eval ByteString
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"string" Value
v
  inj :: ByteString -> Value
inj = Text -> Value
VStr (Text -> Value) -> (ByteString -> Text) -> ByteString -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
decodeUtf8

instance HasValue Scientific where
  proj :: Value -> Eval Scientific
proj (VNum Scientific
n) = Scientific -> Eval Scientific
forall (f :: * -> *) a. Applicative f => a -> f a
pure Scientific
n
  proj Value
v = Text -> Value -> Eval Scientific
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"number" Value
v
  inj :: Scientific -> Value
inj = Scientific -> Value
VNum

instance HasValue Double where
  proj :: Value -> Eval Double
proj (VNum Scientific
n) = Double -> Eval Double
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Scientific -> Double
forall a. RealFloat a => Scientific -> a
toRealFloat Scientific
n)
  proj Value
v = Text -> Value -> Eval Double
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"number" Value
v
  inj :: Double -> Value
inj = Scientific -> Value
VNum (Scientific -> Value) -> (Double -> Scientific) -> Double -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Scientific
forall a. RealFloat a => a -> Scientific
fromFloatDigits

instance {-# OVERLAPS #-} Integral a => HasValue a where
  proj :: Value -> Eval a
proj (VNum Scientific
n) = a -> Eval a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Scientific -> a
forall a b. (RealFrac a, Integral b) => a -> b
round Scientific
n)
  proj Value
v = Text -> Value -> Eval a
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"number" Value
v
  inj :: a -> Value
inj = Scientific -> Value
VNum (Scientific -> Value) -> (a -> Scientific) -> a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral

instance HasValue a => HasValue (Maybe a) where
  proj :: Value -> Eval (Maybe a)
proj Value
VNull = Maybe a -> Eval (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
  proj Value
a = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Eval a -> Eval (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Eval a
forall a. HasValue a => Value -> Eval a
proj Value
a
  inj :: Maybe a -> Value
inj Maybe a
Nothing = Value
VNull
  inj (Just a
a) = a -> Value
forall a. HasValue a => a -> Value
inj a
a

instance HasValue a => HasValue (Vector a) where
  proj :: Value -> Eval (Vector a)
proj (VArr Array
as) = (Thunk -> Eval a) -> Array -> Eval (Vector a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Thunk -> Eval a
forall a. HasValue a => Thunk -> Eval a
proj' Array
as
  proj Value
v = Text -> Value -> Eval (Vector a)
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"array" Value
v
  inj :: Vector a -> Value
inj Vector a
as = Array -> Value
VArr (Array -> Value) -> Array -> Value
forall a b. (a -> b) -> a -> b
$ Value -> Thunk
mkThunk' (Value -> Thunk) -> (a -> Value) -> a -> Thunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. HasValue a => a -> Value
inj (a -> Thunk) -> Vector a -> Array
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector a
as

instance {-# OVERLAPS #-} HasValue (Vector Thunk) where
  proj :: Value -> Eval Array
proj (VArr Array
as) = Array -> Eval Array
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array
as
  proj Value
v = Text -> Value -> Eval Array
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"array" Value
v
  inj :: Array -> Value
inj = Array -> Value
VArr

instance {-# OVERLAPPABLE #-} HasValue a => HasValue [a] where
  proj :: Value -> Eval [a]
proj = (Vector a -> [a]) -> Eval (Vector a) -> Eval [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector a -> [a]
forall a. Vector a -> [a]
V.toList (Eval (Vector a) -> Eval [a])
-> (Value -> Eval (Vector a)) -> Value -> Eval [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Eval (Vector a)
forall a. HasValue a => Value -> Eval a
proj
  inj :: [a] -> Value
inj = Vector a -> Value
forall a. HasValue a => a -> Value
inj (Vector a -> Value) -> ([a] -> Vector a) -> [a] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Vector a
forall a. [a] -> Vector a
V.fromList

instance {-# OVERLAPS #-} HasValue Object where
  proj :: Value -> Eval (HashMap Text (Hideable Thunk))
proj (VObj HashMap Text (Hideable Thunk)
o) = HashMap Text (Hideable Thunk)
-> Eval (HashMap Text (Hideable Thunk))
forall (f :: * -> *) a. Applicative f => a -> f a
pure HashMap Text (Hideable Thunk)
o
  proj Value
v = Text -> Value -> Eval (HashMap Text (Hideable Thunk))
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"object" Value
v
  inj :: HashMap Text (Hideable Thunk) -> Value
inj = HashMap Text (Hideable Thunk) -> Value
VObj

instance {-# OVERLAPS #-} (HasValue a, HasValue b) => HasValue (a -> b) where
  proj :: Value -> Eval (a -> b)
proj Value
v = Text -> Value -> Eval (a -> b)
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"impossible" Value
v
  inj :: (a -> b) -> Value
inj a -> b
f = (Thunk -> Eval Value) -> Value
VFun ((Thunk -> Eval Value) -> Value) -> (Thunk -> Eval Value) -> Value
forall a b. (a -> b) -> a -> b
$ \Thunk
x -> Thunk -> Eval Value
force Thunk
x Eval Value -> (Value -> Eval Value) -> Eval Value
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (a -> Value) -> Eval a -> Eval Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b -> Value
forall a. HasValue a => a -> Value
inj (b -> Value) -> (a -> b) -> a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) (Eval a -> Eval Value) -> (Value -> Eval a) -> Value -> Eval Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Eval a
forall a. HasValue a => Value -> Eval a
proj

instance {-# OVERLAPS #-} (HasValue a, HasValue b, HasValue c) => HasValue (a -> b -> c) where
  proj :: Value -> Eval (a -> b -> c)
proj Value
v = Text -> Value -> Eval (a -> b -> c)
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"impossible" Value
v
  inj :: (a -> b -> c) -> Value
inj a -> b -> c
f = (a -> Value) -> Value
forall a. HasValue a => a -> Value
inj ((a -> Value) -> Value) -> (a -> Value) -> Value
forall a b. (a -> b) -> a -> b
$ \a
x -> (b -> c) -> Value
forall a. HasValue a => a -> Value
inj (a -> b -> c
f a
x)

instance {-# OVERLAPS #-} (HasValue a, HasValue b) => HasValue (a -> Eval b) where
  proj :: Value -> Eval (a -> Eval b)
proj (VFun Thunk -> Eval Value
f) = (a -> Eval b) -> Eval (a -> Eval b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a -> Eval b) -> Eval (a -> Eval b))
-> (a -> Eval b) -> Eval (a -> Eval b)
forall a b. (a -> b) -> a -> b
$ \a
x -> do
    Value
r <- Thunk -> Eval Value
f (Value -> Thunk
mkThunk' (Value -> Thunk) -> Value -> Thunk
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. HasValue a => a -> Value
inj a
x)
    Value -> Eval b
forall a. HasValue a => Value -> Eval a
proj Value
r
  proj (VClos Fun
f Env
env) = (a -> Eval b) -> Eval (a -> Eval b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a -> Eval b) -> Eval (a -> Eval b))
-> (a -> Eval b) -> Eval (a -> Eval b)
forall a b. (a -> b) -> a -> b
$ \a
x -> do
    Value
r <- Ctx -> Fun -> [Arg Thunk] -> Eval Value
evalClos (Env -> Ctx
ctx Env
env) Fun
f ([Arg Thunk] -> Eval Value) -> [Arg Thunk] -> Eval Value
forall a b. (a -> b) -> a -> b
$ [Thunk -> Arg Thunk
forall a. a -> Arg a
Pos (Thunk -> Arg Thunk) -> Thunk -> Arg Thunk
forall a b. (a -> b) -> a -> b
$ Value -> Thunk
mkThunk' (Value -> Thunk) -> Value -> Thunk
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. HasValue a => a -> Value
inj a
x]
    Value -> Eval b
forall a. HasValue a => Value -> Eval a
proj Value
r
  proj Value
v = Text -> Value -> Eval (a -> Eval b)
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"function" Value
v
  inj :: (a -> Eval b) -> Value
inj a -> Eval b
f = (Thunk -> Eval Value) -> Value
VFun ((Thunk -> Eval Value) -> Value) -> (Thunk -> Eval Value) -> Value
forall a b. (a -> b) -> a -> b
$ \Thunk
v -> Thunk -> Eval a
forall a. HasValue a => Thunk -> Eval a
proj' Thunk
v Eval a -> (a -> Eval Value) -> Eval Value
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (b -> Value) -> Eval b -> Eval Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> Value
forall a. HasValue a => a -> Value
inj (Eval b -> Eval Value) -> (a -> Eval b) -> a -> Eval Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Eval b
f

instance {-# OVERLAPS #-} (HasValue a, HasValue b, HasValue c) => HasValue (a -> b -> Eval c) where
  proj :: Value -> Eval (a -> b -> Eval c)
proj (VFun Thunk -> Eval Value
f) = (a -> b -> Eval c) -> Eval (a -> b -> Eval c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a -> b -> Eval c) -> Eval (a -> b -> Eval c))
-> (a -> b -> Eval c) -> Eval (a -> b -> Eval c)
forall a b. (a -> b) -> a -> b
$ \a
x b
y -> do
    VFun Thunk -> Eval Value
g <- Thunk -> Eval Value
f (Value -> Thunk
mkThunk' (Value -> Thunk) -> Value -> Thunk
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. HasValue a => a -> Value
inj a
x)
    Value
r <- Thunk -> Eval Value
g (Value -> Thunk
mkThunk' (Value -> Thunk) -> Value -> Thunk
forall a b. (a -> b) -> a -> b
$ b -> Value
forall a. HasValue a => a -> Value
inj b
y)
    Value -> Eval c
forall a. HasValue a => Value -> Eval a
proj Value
r
  proj (VClos Fun
f Env
env) = (a -> b -> Eval c) -> Eval (a -> b -> Eval c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a -> b -> Eval c) -> Eval (a -> b -> Eval c))
-> (a -> b -> Eval c) -> Eval (a -> b -> Eval c)
forall a b. (a -> b) -> a -> b
$ \a
x b
y -> do
    Value
r <- Ctx -> Fun -> [Arg Thunk] -> Eval Value
evalClos (Env -> Ctx
ctx Env
env) Fun
f ([Arg Thunk] -> Eval Value) -> [Arg Thunk] -> Eval Value
forall a b. (a -> b) -> a -> b
$ Thunk -> Arg Thunk
forall a. a -> Arg a
Pos (Thunk -> Arg Thunk) -> (Value -> Thunk) -> Value -> Arg Thunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Thunk
mkThunk' (Value -> Arg Thunk) -> [Value] -> [Arg Thunk]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a -> Value
forall a. HasValue a => a -> Value
inj a
x, b -> Value
forall a. HasValue a => a -> Value
inj b
y]
    Value -> Eval c
forall a. HasValue a => Value -> Eval a
proj Value
r
  proj Value
v = Text -> Value -> Eval (a -> b -> Eval c)
forall a. Text -> Value -> Eval a
throwTypeMismatch Text
"function" Value
v
  inj :: (a -> b -> Eval c) -> Value
inj a -> b -> Eval c
f = (a -> Value) -> Value
forall a. HasValue a => a -> Value
inj ((a -> Value) -> Value) -> (a -> Value) -> Value
forall a b. (a -> b) -> a -> b
$ \a
x -> (b -> Eval c) -> Value
forall a. HasValue a => a -> Value
inj (a -> b -> Eval c
f a
x)

throwTypeMismatch :: Text -> Value -> Eval a
throwTypeMismatch :: forall a. Text -> Value -> Eval a
throwTypeMismatch Text
expected =
  EvalError -> Eval a
forall a. EvalError -> Eval a
throwE
    (EvalError -> Eval a) -> (Value -> EvalError) -> Value -> Eval a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> EvalError
TypeMismatch Text
expected
    (Text -> EvalError) -> (Value -> Text) -> Value -> EvalError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Text
valueType

inj' ::
  (HasValue a, HasValue b) =>
  (a -> b) ->
  (Value -> Eval Value)
inj' :: forall a b.
(HasValue a, HasValue b) =>
(a -> b) -> Value -> Eval Value
inj' a -> b
f Value
v = b -> Value
forall a. HasValue a => a -> Value
inj (b -> Value) -> (a -> b) -> a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f (a -> Value) -> Eval a -> Eval Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Eval a
forall a. HasValue a => Value -> Eval a
proj Value
v

inj'' ::
  (HasValue a, HasValue b, HasValue c) =>
  (a -> b -> c) ->
  Value ->
  Value ->
  Eval Value
inj'' :: forall a b c.
(HasValue a, HasValue b, HasValue c) =>
(a -> b -> c) -> Value -> Value -> Eval Value
inj'' a -> b -> c
f Value
v1 Value
v2 = c -> Value
forall a. HasValue a => a -> Value
inj (c -> Value) -> Eval c -> Eval Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> b -> c) -> Eval a -> Eval b -> Eval c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> b -> c
f (Value -> Eval a
forall a. HasValue a => Value -> Eval a
proj Value
v1) (Value -> Eval b
forall a. HasValue a => Value -> Eval a
proj Value
v2)