[Haskell-cafe] Dependently typed fold in GHC/Haskell
Christiaan Baaij
christiaan.baaij at gmail.com
Wed Nov 19 12:40:45 UTC 2014
Dear Cafe,
I'm trying to convert the following Idris code, which compiles:
> gfold : {p : Nat -> Type}
> -> ((l : Nat) -> a -> p l -> p (S l))
> -> p 0 -> Vect k a -> p k
> gfold _ z Nil = z
> gfold f z ((::) {n} x xs) = f n x (gfold f z xs)
>
> gconcat : {m : Nat} -> Vect n a -> Vect m a -> Vect (n + m) a
> gconcat {m} xs ys = gfold {p} f ys xs
> where
> p : Nat -> Type
> p l = Vect (l + m) a
>
> f : (l : Nat) -> a -> Vect (l + m) a -> Vect (S (l + m)) a
> f _ x r = x :: r
To Haskell + various GHC extensions, which gives me type errors:
> {-# LANGUAGE DataKinds, GADTs, KindSignatures, TypeOperators, RankNTypes,
> ScopedTypeVariables, TypeFamilies #-}
>
> import Data.Proxy
>
> data Nat = Z | S Nat
>
> type family Plus (x :: Nat) (y :: Nat) :: Nat where
> Plus Z y = y
> Plus (S n) y = S (Plus n y)
>
> data Vec :: * -> Nat -> * where
> Nil :: Vec a Z
> (:>) :: a -> Vec a n -> Vec a (S n)
>
> gfold :: Proxy (p :: Nat -> *)
> -> (forall l . Proxy l -> a -> p l -> p (S l))
> -> p Z -> Vec a k -> p k
> gfold Proxy f z Nil = z
> gfold Proxy f z (x :> xs) = f Proxy x (gfold Proxy f z xs)
>
> type family P (a :: *) (m :: Nat) (l :: Nat) :: * where
> P a m l = Vec a (Plus l m)
>
> gconcat :: forall n m a . Vec a n -> Vec a m -> Vec a (Plus n m)
> gconcat xs ys = gfold p f ys xs
> where
> p :: Proxy (P a m)
> p = Proxy
>
> f :: forall (l :: Nat) . Proxy l -> a -> Vec a (Plus l m)
> -> Vec a (S (Plus l m))
> f _ x r = x :> r
I get the following errors:
> VecTest.hs:25:25:
> Couldn't match type ‘l’ with ‘Plus l m’
> ‘l’ is a rigid type variable bound by
> a type expected by the context:
> Proxy l -> a -> Vec a l -> Vec a ('S l)
> at VecTest.hs:25:17
> Expected type: Proxy l -> a -> Vec a l -> Vec a ('S l)
> Actual type: Proxy l
> -> a -> Vec a (Plus l m) -> Vec a ('S (Plus l m))
> Relevant bindings include
> p :: Proxy (P a m) (bound at VecTest.hs:28:5)
> f :: forall (l :: Nat).
> Proxy l -> a -> Vec a (Plus l m) -> Vec a ('S (Plus l m))
> (bound at VecTest.hs:32:5)
> ys :: Vec a m (bound at VecTest.hs:25:12)
> gconcat :: Vec a n -> Vec a m -> Vec a (Plus n m)
> (bound at VecTest.hs:25:1)
> In the second argument of ‘gfold’, namely ‘f’
> In the expression: gfold p f ys xs
>
> VecTest.hs:25:27:
> Couldn't match type ‘m’ with ‘'Z’
> ‘m’ is a rigid type variable bound by
> the type signature for
> gconcat :: Vec a n -> Vec a m -> Vec a (Plus n m)
> at VecTest.hs:24:21
> Expected type: Vec a 'Z
> Actual type: Vec a m
> Relevant bindings include
> p :: Proxy (P a m) (bound at VecTest.hs:28:5)
> f :: forall (l :: Nat).
> Proxy l -> a -> Vec a (Plus l m) -> Vec a ('S (Plus l m))
> (bound at VecTest.hs:32:5)
> ys :: Vec a m (bound at VecTest.hs:25:12)
> gconcat :: Vec a n -> Vec a m -> Vec a (Plus n m)
> (bound at VecTest.hs:25:1)
> In the third argument of ‘gfold’, namely ‘ys’
> In the expression: gfold p f ys xs
Is this kind of type-level programming just not yet possible in GHC?
Or am I simply doing it wrong?
Cheers,
Christiaan
More information about the Haskell-Cafe
mailing list