-
Notifications
You must be signed in to change notification settings - Fork 26
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
Use rosetree to store capability type. #212
Conversation
What is this? |
Traits implemented by one class are combined using |
OK. So, is it fair to say that this PR should be renamed "Adding conjunction composition for traits"? |
Bump @EliasC … |
I would be reluctant to call it so, for "adding conjunction composition" implies that typechecker catches malformed usages and emit correct C code. On the contrary, this PR only adds the rose tree data structure to store all the traits. |
map TraitType ((toList . typeTree) capability) | ||
typesFromCapability ty = | ||
error $ "Types.hs: Can't get the traits of non-capability type " | ||
++ showWithKind ty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the name traitsFromCapability
better since it specifies the granularity of the resulting types. It is not clear to me (without reading the code) what typesFromCapability
gives me for A * (B + C)
, while with traitsFromCapability
it's obvious that it is [A, B, C]
(in some order).
Have looked at all the cases where |
let | ||
par_types = map toList $ map (fmap TraitType) ts | ||
in | ||
concatMap collect ts ++ [par_types] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conjunctiveTraitsFromCapability
is a better name I think, if this function takes a conjunctive type A*B
and returns [[A], [B]]
(I don't see how the third level of list-nesting is used, but maybe you get the point). parallelTypes
is confusing since we have a Par
type.
The return type just strengthens my point I think. Reading the name and the type I have no way of knowing that all the types in the resulting list are actually trait types! |
Yes, |
Could you give a quick explanation of what it returns as well? I didn't get why it's a list of lists of lists. |
|
||
instance Traversable RoseTree where | ||
traverse f (Leaf i) = Leaf <$> f i | ||
traverse f (RoseTree op ts) = RoseTree op <$> traverse (traverse f) ts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice how the structure is made instances of these type classes so that normal map
, mapM
, etc. works!
That's true, but the function name could be changed to arbitrary strings, while the signature is checked all the time. It's good to rely on the signature instead of the name. BTW, we don't have trait type, only
I think it's because there are multiple levels of conjunctive traits, since it's a tree. |
That's hardly an argument to choose bad names though :) I will drop this for now and bring it up again if it causes problems while programming. |
|
||
is_val :: FieldDecl -> TypecheckM () | ||
is_val f = unless (isValField f) $ tcError $ | ||
printf "'%s' is not val field" $ show f |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message should be improved (something like Disjunctive traits A and B cannot have overlapping mutable field requirements
), but I'm ready to push that to a later commit.
So something like this? The innermost lists are collection of disjunctive traits that may share fields. The sibling lists of those lists contain traits that are all conjunctive between lists. Each list of these lists contain the traits of different levels of the tree. It feels like you should be able to do this with only two levels so that only the first two "steps" above are needed. Please let me know if you can shed any light on this! |
When the discussed issues are fixed, I think this is ready to be merged! |
(+rebasing) |
It's possible that I overcomplicated the situation; for
|
Thanks for the explanation! Let's leave it as it is and refactor it if we find a need for it. There is still a spelling mistake in One comment on the error message of overlapping fields though. Right now the message is
which describes a solution to get rid of the error, but not the reason there was an error in the first place. I suggest instead
which describes what design choice lead to the error, which is more useful in teaching the programmer how to avoid errors like this in the future. If you want to also describe a solution you could add |
I have found the idea of using camel and snake to distinguish the public and private functions very helpful. Encourage others to try it out. |
I would rather suggest that we come up with some general guidelines for writing code, instead of everyone choosing what to do. Now, @albertnetymk suggests to use snake case for private functions. I suggest that everyone uses snakel case: |
@albertnetymk For the nth time point you to our own guidelines for contibuting:
Although I prefer camelCase (as you know), that's not why I'm arguing that you should use it. My point is that you need to respect the conventions of the code you're contributing to. Here is the
All the functions visible here are have descriptive names in camelCase without abbreviations. When you add something to this context and ignore these conventions, you deteriorate the quality of the code. It would make more sense to rename I agree with @kikofernandez. We need to agree on a convention that we can all follow. It is obvious that these discussions have no effect. |
I will merge this now, but we should continue the discussion about coding conventions. I started an issue for it: #224 |
Use rosetree to store capability type.
In this specific case, we have the convention -- you linked to it. @albertnetymk just doesn't adhere to it, so this is a problem of programmer discipline/weak enforcing, not lack of convention. |
fmap f (Leaf i) = Leaf $ f i | ||
fmap f (RoseTree op ts) = RoseTree op $ map (fmap f) ts | ||
|
||
instance Foldable RoseTree where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is breaking the build, Foldable
is in Prelude only since ghc 7.10
No description provided.