Skip to content

Instantly share code, notes, and snippets.

@JakobBruenker
Last active January 30, 2020 14:45
Show Gist options
  • Save JakobBruenker/6a87367b1eded2f0a18b73e2333b10c2 to your computer and use it in GitHub Desktop.
Save JakobBruenker/6a87367b1eded2f0a18b73e2333b10c2 to your computer and use it in GitHub Desktop.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE LambdaCase #-}
module HList where
import Prelude hiding (head, tail, zip)
import GHC.Exts (Constraint)
data HList :: [*] -> * where
Nil :: HList '[]
Cons :: a -> HList l -> HList (a ': l)
instance Show (HList '[]) where
show Nil = "Nil"
instance (Show a, Show (HList l)) => Show (HList (a ': l)) where
show (Cons x xs) = "Cons " ++ show x ++ " (" ++ show xs ++ ")"
head :: HList (a ': l) -> a
head (Cons h _) = h
tail :: HList (a ': l) -> HList l
tail (Cons _ t) = t
class Fun (l :: [*]) (r :: *) t | l r -> t where
apply :: t -> HList l -> r
instance Fun '[] r r where
apply x Nil = x
instance Fun as r t => Fun (a ': as) r (a -> t) where
apply f (Cons h t) = apply (f h) t
class Zip (l :: [*]) (k :: [*]) (t :: [*]) | l k -> t where
zip :: HList l -> HList k -> HList t
instance Zip '[] '[] '[] where
zip Nil Nil = Nil
instance Zip as bs t => Zip (a ': as) (b ': bs) ((a, b) ': t) where
zip (Cons a as) (Cons b bs) = Cons (a, b) (zip as bs)
instance ("Error!" ~ "List length are unequal!", Zip as '[] t) => Zip (a ': as) '[] t where
zip = \case
instance ("Error!" ~ "List length are unequal!", Zip '[] bs t) => Zip '[] (b ': bs) t where
zip = \case
someList :: HList [Bool, Char, Int]
someList = Cons True (Cons 'c' (Cons 1 Nil))
anotherList :: HList [Maybe (), [a], Double]
anotherList = Cons (Just ()) (Cons [] (Cons 2.0 Nil))
zippedList :: HList [(Bool, Maybe ()), (Char, [a]), (Int, Double)]
zippedList = zip someList anotherList
main :: IO ()
main = print $ apply (,,) someList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment