-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Matching #3
Comments
Note that even though the syntax for rules is written
That's probably fine: the goal is not necessarily to discharge the entire constraint, but to rewrite it in a way which makes ghc happy. With the rule
I am happy to hear that this rewrite rule doesn't fire, because it looks extremely unsound!
I must not quite understand the program you have in mind, because it's working for me. Well, kind of:
Without typelevel-rewrite-rules, I don't quite get an error about a missing
If I add
|
Foolishly I didn't save the code that was causing me problems. And noq I can't recreate the exact same problem. Thanks! |
I've recreated the bug. Unzip and compile Flatten.hs. It works. Remove the line with a comment, and it doesn't compile. The removed line corresponds exactly to an equality in the Rules.hs file. |
Wow, thanks for that tricky test case, it manages to exercises a ton of corner cases at once! Many of those corner cases are not supported by version 0.1 or at all, so here is the long list of changes which are required in order to make the file compile with that line removed. To begin with, a few things which aren't technically a problem with typelevel-rewrite-rules, but probably indicates that the documentation could be improved. First,
with
I don't know why ghc doesn't complain that the Next, the Okay, now for the changes which are needed because of bugs in typelevel-rewrite-rules. First, because of #4 , switch from Next, switch to the HEAD version of typelevel-rewrite-rules in order to take the given constraints into account. At this point, the type error about a missing
The problem is that the wanted constraint used to be
That matches the given constraints, but the rewritten version doesn't. Does that mean typelevel-rewrite-rules should also rewrite the given constraints? I'm not sure yet. Anyway, we can solve the problem by manually replacing the Here is the result after all those changes: {-# LANGUAGE ConstraintKinds, DataKinds, TypeFamilies, TypeOperators, UndecidableInstances #-}
module Rules where
import GHC.TypeLits
data MyNat = Z | S MyNat
class Shape (s :: [Nat])
instance Shape '[]
instance (Shape s, KnownNat n) => Shape (n ': s)
type family Rank (s :: [Nat]) :: MyNat where
Rank '[] = 'Z
Rank (n : ns) = 'S (Rank ns)
type family Take (n :: MyNat) (xs :: [Nat]) :: [Nat] where
Take 'Z xs = '[]
Take ('S n) (x ': xs) = x ': Take n xs
type family Drop (n :: MyNat) (xs :: [Nat]) :: [Nat] where
Drop 'Z xs = xs
Drop ('S n) (x ': xs) = Drop n xs
type family (++) (xs :: [Nat]) (ys :: [Nat]) :: [Nat] where
(++) '[] ys = ys
(++) (x ': xs) ys = x ': (xs ++ ys)
type family Last (xs :: [Nat]) where
Last '[x] = x
Last (x ': xs) = Last xs
type family Init (xs :: [Nat]) where
Init '[x] = '[]
Init (x ': xs) = x ': Init xs
type family Pred (n :: MyNat) :: MyNat where
Pred ('S n) = n
type ListLast xs =
Drop (Pred (Rank xs)) xs ~ '[Last xs] {-# LANGUAGE AllowAmbiguousTypes, DataKinds, FlexibleContexts, RankNTypes, ScopedTypeVariables, TypeApplications, TypeFamilies, TypeOperators #-}
{-# OPTIONS_GHC -fplugin TypeLevel.Rewrite
-fplugin-opt=TypeLevel.Rewrite:Rules.ListLast
#-}
module Flatten where
import GHC.TypeLits
import Rules
data Array (sh :: [Nat]) a
rerank :: forall n i o sh a b .
(Drop n sh ~ i, Shape sh, Shape o, Shape (Take n sh ++ o)) =>
(Array i a -> Array o b) -> Array sh a -> Array (Take n sh ++ o) b
rerank = undefined
ravel :: forall s sh a .
(Shape sh, KnownNat s) =>
Array '[s] (Array sh a) -> Array (s:sh) a
ravel = undefined
flatten :: forall shx shy a .
(KnownNat (Last shx), Shape shx, Shape shy, Shape (shx ++ shy),
-- Drop (Pred (Rank shx)) shx ~ '[Last shx], -- With a lot of effort, this line can be removed :)
(shx ++ shy) ~ (Take (Pred (Rank shx)) shx ++ ('[Last shx] ++ shy))
) =>
Array shx (Array shy a) -> Array (shx ++ shy) a
flatten = rerank @(Pred (Rank shx)) ravel |
Wow, that was a stupid mistake of mine. I'm glad my example uncovered some other problems as well. |
At some point I parse the LHS and the RHS into trees, and I assume that internal nodes are type constructors applied to type arguments, and that leaves are type constructors applied to zero arguments. I am guessing that the problem is that a |
That was indeed the problem, and I have now fixed #4, so numeric literals are now supported! There is still the tricky business of given vs wanted constraints. You know a lot about Haskell compilers, maybe you can help? I don't have a good story for what typelevel-rewrite-rules should do with the given constraints. Version 0.1 completely ignores them, the HEAD version does a little bit better, but the What the HEAD version is currently doing is as follows. I've noticed that most of the given constraints have the form Does it seem sound to apply the rewrite rules to the given constraints? My intuition tells me that I should either leave them alone or apply the rewrite rules in reverse, but that would not have helped in your example. Clearly, I need a better mental model of the relationship between the wanted and the given constraints, beyond "givens are what we already know and wanteds are what we want to prove". |
I don't know enough about ghc's constraint solving to have much of an opinion. |
I suspect that the rewrite rules use exact matching for the RHS instead of matching/unification.
Here's a problem I have:
GHC says:
Could not deduce: Drop (Length sh1 - 1) sh1 ~ '[s0]
where s0 is not a variable I've not quantified over, so I can't mention it.
This rule doesn't match:
type ListLast xs x =
Drop (Length xs - 1) xs ~ '[x]
Nor does this one:
type ListLast xs =
Drop (Length xs - 1) xs ~ '[Last xs]
Any suggestions?
The text was updated successfully, but these errors were encountered: