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

[#265] Make SuperComposition less brittle #266

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Unreleased
=====

* [#265](https://github.com/serokell/universum/issues/265):
Make `SuperComposition` inference less brittle, and give it four
type parameters.

* [#252](https://github.com/serokell/universum/pull/252):
Remove `Option` re-export. Use `Maybe` instead.

Expand Down
2 changes: 1 addition & 1 deletion benchmark/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ bgroupSuperComposition = bgroup "(...)"
where
super10 :: [()] -> Bool
super10 = null
... ((: []) ... Unsafe.head ... pure ... Unsafe.head
... ((: []) ... Unsafe.head ... (:[]) ... Unsafe.head
... (: [(), (), (), ()]) ... Unsafe.head ... (: []) ... Unsafe.head
... (: [()]) ... Unsafe.head ... (: [(), ()]) ... Unsafe.head :: [()] -> [()])

Expand Down
20 changes: 12 additions & 8 deletions src/Universum/VarArg.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ module Universum.VarArg
-- >>> import Data.List (zip5)

-- | This type class allows to implement variadic composition operator.
class SuperComposition a b c | a b -> c where
class SuperComposition x y b r | x y b -> r where
-- | Allows to apply function to result of another function with multiple
-- arguments.
--
-- >>> (show ... (+)) 1 2
-- >>> (show ... (+)) (1 :: Int) 2
-- "3"
-- >>> show ... 5
-- >>> show ... (5 :: Int)
-- "5"
-- >>> (null ... zip5) [1] [2] [3] [] [5]
-- True
--
-- Note that the arity of the second argument must be apparent to the type
-- checker, which is why the above examples require type annotations for numeric
-- literals.
--
-- Inspired by <http://stackoverflow.com/questions/9656797/variadic-compose-function>.
--
-- ==== Performance
Expand All @@ -45,16 +49,16 @@ class SuperComposition a b c | a b -> c where
-- disappear due to very general inferred type. However, functions without type
-- specification but with applied @INLINE@ pragma are fast again.
--
(...) :: a -> b -> c
(...) :: (x -> y) -> b -> r

infixl 8 ...

instance {-# INCOHERENT #-} (a ~ c, r ~ b) =>
SuperComposition (a -> b) c r where
instance {-# OVERLAPPABLE #-} (x ~ b, y ~ r) =>
SuperComposition x y b r where
f ... g = f g
{-# INLINE (...) #-}

instance {-# INCOHERENT #-} (SuperComposition (a -> b) d r1, r ~ (c -> r1)) =>
SuperComposition (a -> b) (c -> d) r where
instance {-# OVERLAPPING #-} (SuperComposition x y d r1, r ~ (c -> r1)) =>
SuperComposition x y (c -> d) r where
(f ... g) c = f ... g c
{-# INLINE (...) #-}