From 47918282bb3a87041f28e6a419e311c2c76dcad0 Mon Sep 17 00:00:00 2001 From: David Feuer Date: Mon, 9 May 2022 16:21:15 -0400 Subject: [PATCH] [#265] Make SuperComposition less brittle * Use overlapping instances instead of incoherent ones. Fixes #265. * Make the first argument of `...` a function unconditionally, before instance selection. This can theoretically improve inference slightly, though it probably doesn't have much impact in practice. --- CHANGES.md | 4 ++++ benchmark/Main.hs | 2 +- src/Universum/VarArg.hs | 12 ++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ece3451..3b4148c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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. diff --git a/benchmark/Main.hs b/benchmark/Main.hs index b507209..71703a2 100644 --- a/benchmark/Main.hs +++ b/benchmark/Main.hs @@ -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 :: [()] -> [()]) diff --git a/src/Universum/VarArg.hs b/src/Universum/VarArg.hs index 18f7cae..de0ee80 100644 --- a/src/Universum/VarArg.hs +++ b/src/Universum/VarArg.hs @@ -19,7 +19,7 @@ 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. -- @@ -45,16 +45,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 (...) #-}