For some application I need vectors of length $2^n$. To enforce that the lengths match for some operations, I defined my type with ist applicative instance as follows:
{-# LANGUAGE GADTs, DataKinds, FlexibleInstances, FlexibleContexts #-}
data Nat = Z | N Nat
data Vector n t where
S :: t -> Vector Z t
V :: Vector n t -> Vector n t -> Vector (N n) t
instance Functor (Vector n) where
fmap f (S t ) = S (f t)
fmap f (V t t') = V (fmap f t) (fmap f t')
instance Applicative (Vector Z) where
pure = S
S f <*> S a = S (f a)
instance Applicative (Vector n) => Applicative (Vector (N n)) where
pure a = let a' = pure a in V a' a'
V f f' <*> V a a' = V (f <*> a) (f' <*> a')
The language extensions I chose as suggested by ghci to make the code compile. The whole structure is inspired by How to make fixed-length vectors instance of Applicative?.
Trouble starts when I try to use it:
instance Num t => Num (Vector n t) where
v + v' = (+) <$> v <*> v'
(*) = undefined
abs = undefined
signum = undefined
fromInteger = undefined
negate = undefined
Adding these lines Triggers following error:
• Could not deduce (Applicative (Vector n)) arising from a use of ‘<*>’ from the context: Num t bound by the instance declaration at ...
• In the expression: (+) v <> v' In an equation for ‘+’: v + v' = (+) v <> v' In the instance declaration for ‘Num (Vector n t)’
I'm using Haskell Platform 8.0.2-a on Windows 7.
Any idea what's going? In the linked question the same trick seems to work!? (Adding KindSignatures in the first line does not help, and without FlexibleInstances/Contexts I get a Compiler error.)
instance (Num t, Applicative (Vector n)) => Num (Vector n t) where
since otherwise you can indeed not use(<*>)
. – Willem Van OnsemF x :: Nat
is a type family which gets "stuck" (say,F Bool
is not defined) the compiler is not allowed to resolve, say,Applicative (Vector (F Bool))
since it can not evaluateF Bool
to a concreteNat
, so it can not choose an instance. It is weird to have type-expressions of kindNat
which do not evaluate to a concreteNat
, but that's how GHC works. – chiZ
orN x
in the type. If there is a type variable liken
or a "stuck" type familyF Bool
, GHC does not know what instance to pick and will not resolve the constraint. There are some ways around that, e.g. exploiting suitable GADTs to prove "n
is indeed one of the two possible forms" -- this is a bit advanced, however, so I'd recommend to get familiar with GADTs first. – chi