dhall-1.35.0: src/Dhall/Context.hs
{-# LANGUAGE DeriveFunctor #-}
-- | This is a utility module that consolidates all `Context`-related operations
module Dhall.Context (
-- * Context
Context
, empty
, insert
, match
, lookup
, toList
) where
import Data.Text (Text)
import Prelude hiding (lookup)
{-| A @(Context a)@ associates `Data.Text.Text` labels with values of type @a@.
Each `Data.Text.Text` label can correspond to multiple values of type @a@
The `Context` is used for type-checking when @(a = Expr X)@
* You create a `Context` using `empty` and `insert`
* You transform a `Context` using `fmap`
* You consume a `Context` using `lookup` and `toList`
The difference between a `Context` and a `Data.Map.Map` is that a `Context`
lets you have multiple ordered occurrences of the same key and you can
query for the @n@th occurrence of a given key.
-}
newtype Context a = Context { getContext :: [(Text, a)] }
deriving (Functor)
-- | An empty context with no key-value pairs
empty :: Context a
empty = Context []
-- | Add a key-value pair to the `Context`
insert :: Text -> a -> Context a -> Context a
insert k v (Context kvs) = Context ((k, v) : kvs)
{-# INLINABLE insert #-}
{-| \"Pattern match\" on a `Context`
> match (insert k v ctx) = Just (k, v, ctx)
> match empty = Nothing
-}
match :: Context a -> Maybe (Text, a, Context a)
match (Context ((k, v) : kvs)) = Just (k, v, Context kvs)
match (Context [] ) = Nothing
{-# INLINABLE match #-}
{-| Look up a key by name and index
> lookup _ _ empty = Nothing
> lookup k 0 (insert k v c) = Just v
> lookup k n (insert k v c) = lookup k (n - 1) c
> lookup k n (insert j v c) = lookup k n c -- k /= j
-}
lookup :: Text -> Int -> Context a -> Maybe a
lookup _ _ (Context [] ) =
Nothing
lookup x n (Context ((k, v):kvs)) =
if x == k
then if n == 0
then Just v
else lookup x (n - 1) (Context kvs)
else lookup x n (Context kvs)
{-# INLINABLE lookup #-}
{-| Return all key-value associations as a list
> toList empty = []
> toList (insert k v ctx) = (k, v) : toList ctx
-}
toList :: Context a -> [(Text, a)]
toList = getContext
{-# INLINABLE toList #-}