Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Created November 18, 2014 00:05
Show Gist options
  • Save NicolasT/fe353824766da2d27660 to your computer and use it in GitHub Desktop.
Save NicolasT/fe353824766da2d27660 to your computer and use it in GitHub Desktop.
Type-safe SQL select queries
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ConstraintKinds #-}
module Main where
import GHC.Exts
import GHC.TypeLits
data HasColumn = HasColumn | NoSuchColumn
type family Elem (x :: k) (xs :: [k]) :: Constraint
type instance Elem x xs = (Elem' x xs ~ 'HasColumn)
type family Elem' (x :: k) (xs :: [k]) :: HasColumn where
Elem' x '[] = NoSuchColumn
Elem' x (x ': xs) = 'HasColumn
Elem' x (y ': xs) = Elem' x xs
data Column (name :: Symbol) :: * where
Column :: Column name
data Table (name :: Symbol) (columns :: [Symbol]) :: * where
Table :: Table name columns
data Query where
Select :: Elem c cs => Table n cs -> Column c -> Query
select :: Elem c cs => Table n cs -> Column c -> Query
select = Select
firstName :: Column "first_name"
lastName :: Column "last_name"
(firstName, lastName) = (Column, Column)
type Users = Table "users" ["first_name", "last_name"]
users = Table :: Users
goodQuery :: Query
goodQuery = select users firstName
email :: Column "email"
email = Column
badQuery :: Query
badQuery = select users email
main :: IO ()
main = return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment