Skip to content
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

Inlinable and Logic Optimisations #614

Merged
merged 15 commits into from
Oct 2, 2018

Conversation

FintanH
Copy link
Collaborator

@FintanH FintanH commented Oct 2, 2018

  • Add INLINABLE pragmas to new Dhall.Map functions, as well as Eq and Functor instances for Expr
  • Reworked some Core normalization logic to just look at the head instead of transforming the whole Map into a list

@FintanH
Copy link
Collaborator Author

FintanH commented Oct 2, 2018

Hey @Gabriel439 I can't seem to reproduce the error in ghci with the counterexample 🤔 Any chance you could give me a hand with it? Thanks!

deriving (Functor, Foldable, Generic, Traversable, Show, Eq, Data)
deriving (Foldable, Generic, Traversable, Show, Data)

instance (Eq s, Eq a) => Eq (Expr s a) where
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How critical is the INLINABLE Eq instance for performance? The reason I ask is that it's going to be the most error-prone instance to maintain due to the wildcard match at the end, so if we forget to add Eq support for a newly-introduced constructor the compiler won't warn us.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I don't think it adds much. I can remove it :)

src/Dhall/Map.hs Outdated
>
> head k (singleton k v) = Just (k, v)
-}
head :: Ord k => Map k v -> Maybe (k, v)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of head/tail we could do:

uncons :: Ord k => Map k v -> Maybe (k, v, Map k v)

... that way we don't need to pattern match on a Maybe twice since we know that if the head succeeds then the tail will always succeed, too

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


-- | Traverse all of the key-value pairs in a `Map`, in their original order
traverseWithKey
:: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b)
traverseWithKey f m = fmap fromList (traverse f' (toList m))
where
f' (k, a) = fmap ((,) k) (f k a)
{-# INLINABLE traverseWithKey #-}

traverseWithKey_
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have this, we no longer need the intermediate Process newtype defined in the Dhall.TypeCheck module. I only added that type just for the Monoid instance, but if we replace foldMapWithKey with traverseWithKey_ then we don't need to wrap the process action in the Process newtype

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, don't forget to add documentation for the traverseWithKey_ function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh interesting! I'll check that out

@Gabriella439
Copy link
Collaborator

@FintanH: I can reproduce the error:

>>> let e = UnionLit "" (Embed (Import {importHashed = ImportHashed {hash = Nothing, importType = Remote (URL {scheme = HTTPS, authority = "", path = File {directory = Directory {components = []}, file = ""}, query = Nothing, fragment = Nothing, headers = Nothing})}, importMode = Code})) (Map (Data.Map.fromList [("",ListIndexed),("a",ListLast)]) ["a",""])
>>> isNormalized e
False
>>> normalize e == e
True

It's because of the change you made to the Eq instance to Map. I think the right thing to do is to go back to deriving the Eq instance for Dhall.Map.Map and I'll explain why in the related thread on the other pull request

@FintanH
Copy link
Collaborator Author

FintanH commented Oct 2, 2018

I also added the <> change I mentioned #612 (review)

@Gabriella439 Gabriella439 merged commit c76c749 into dhall-lang:gabriel/new_map_2 Oct 2, 2018
@Gabriella439
Copy link
Collaborator

Thank you! 🙂

@FintanH FintanH deleted the fintan/new-map branch October 3, 2018 08:02
jneira pushed a commit to eta-lang/dhall-haskell that referenced this pull request Oct 3, 2018
* Cleanup

* Centralize all `Map`-related operations

* Use custom `Map` implementation

* Inline and specialise functions

* Custom Eq. Use inlinable

* Mark inlinable

* Remove SCC annotations

* mappend from Semigroup

* mappend from Semigroup

* Clean up of Map, Expr Eq, and TypeCheck
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants