Я пытаюсь наложить ограничение на уровне типа, согласно которому список уровня типа должен иметь ту же длину, что и переносимый Nat уровня типа. Например, при использовании пакета Length from singletons [1]:
data (n ~ Length ls) => NumList (n :: Nat) (ls :: [*])
test :: Proxy (NumList 2 '[Bool, String, Int])
test = Proxy
Я не ожидал, что этот код будет компилироваться, поскольку есть несоответствие.
РЕДАКТИРОВАТЬ: как упоминал dfeuer, контексты Datatype не являются хорошей идеей. Я могу провести сравнение на уровне значений, но я хочу иметь возможность делать это на уровне типа:
class NumListLen a
sameLen :: Proxy a -> Bool
instance (KnownNat n, KnownNat (Length m)) => NumListLen (NumList n m) where
sameLen = const $ (natVal (Proxy :: Proxy n)) == (natVal (Proxy :: Proxy (Length m)))
~~~~
РЕДАКТИРОВАТЬ: Sorta ответила на мой собственный вопрос, просто добавив ограничение к экземпляру:
class NumListLen a
sameLen :: Proxy a -> Bool
instance (KnownNat n, KnownNat (Length m), n ~ Length m) => NumListLen (NumList n m) where
sameLen = const $ (natVal (Proxy :: Proxy n)) == (natVal (Proxy :: Proxy (Length m)))
/home/aistis/Projects/SingTest/SingTest/app/Main.hs:333:13:
Couldn't match type ‘3’ with ‘2’
In the second argument of ‘($)’, namely ‘sameLen test’
In a stmt of a 'do' block: print $ sameLen test
In the expression:
do { print $ sameLen test;
putStrLn "done!" }
Data.Singletons.Prelude.Eq
? Я не знаю, что с этим делать, но вполне может быть способ попроще. - person dfeuer   schedule 13.01.2016