Skip to content

Instantly share code, notes, and snippets.

@ekmett
Created August 4, 2016 07:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ekmett/ff3088d1e401b967d6b653a600359ea4 to your computer and use it in GitHub Desktop.
Save ekmett/ff3088d1e401b967d6b653a600359ea4 to your computer and use it in GitHub Desktop.
horrible TypeApplications hack for Chris Done
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
-- | This module provides a way to name the fields in a regular
-- Haskell tuple and then look them up later, statically.
module NamedTuple where
import Data.String
import Language.Haskell.TH
import Data.Proxy
import GHC.TypeLits
-- | The syntax and the type of a field assignment.
data l := t where
Set :: KnownSymbol l => t -> l := t
symbolVal_ :: forall n. KnownSymbol n => String
symbolVal_ = symbolVal (Proxy @n)
-- Simple show instance for a field.
instance Show t => Show (l := t) where
show (Set t) = symbolVal_ @l ++ " := " ++ show t
-- | Means to search for a field within a tuple.
-- We could add `set` to this, or just have a `lens` method
-- which generates a lens for that field.
class Has (l :: Symbol) r a | l r -> a where
get :: r -> a
-- Instances which we could easily generate with TH.
instance Has l (l := a, u0) a where get (Set a,_) = a
instance Has l (u0, l := a) a where get (_,Set a) = a
instance Has l (l := a, u0, u1) a where get (Set a,_,_) = a
instance Has l (u0, l := a, u1) a where get (_,Set a,_) = a
instance Has l (u0, u1, l := a) a where get (_,_,Set a) = a
mentioned =
(
Set @"url" "https://api.github.com/repos/commercialhaskell/intero/issues/64",
Set @"title" "Support GHCJS",
Set @"user" (
Set @"login" "themoritz",
Set @"id" 3522732
)
)
-- get @"url" mentioned -- now works, you can keep the old := constructor at the value level if you prefer and make 'Set' a combinator.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment