quickcheck
quickcheck copied to clipboard
‘apply’ and ‘Fn’ for different arities
The following are used in containers
apply2 :: Fun (a, b) c -> a -> b -> c
apply2 f a b = apply f (a, b)
apply3 :: Fun (a, b, c) d -> a -> b -> c -> d
apply3 f a b c = apply f (a, b, c)
I see two directions we can go. We can supply those functions, along with:
pattern Fn :: (a -> b) -> Fun a b
pattern Fn f <- Fun _ f
pattern Fn2 :: (a -> b -> c) -> Fun (a, b) c
pattern Fn2 f <- Fun _ (curry -> f)
pattern Fn3 :: (a -> b -> c -> d) -> Fun (a, b, c) d
pattern Fn3 f <- Fun _ (curry3 -> f)
curry3 f a b c = f (a, b, c)
now it can be written
pInsertWithKeyStrict :: Fun (Int, Int) Int -> Int -> IntMap Int -> Bool
pInsertWithKeyStrict (Fn2 f) v m = isBottom $ M.insertWith f bottom v m
pInsertLookupWithKeyKeyStrict :: Fun (Int, Int, Int) Int -> Int -> IntMap Int -> Bool
pInsertLookupWithKeyKeyStrict (Fn3 f) v m = isBottom $ M.insertLookupWithKey f bottom v m
Alternatively we could use some type class trickery to provide a single function and pattern that supersede apply{,2,3}
and Fn{,2,3}
. So that the user never has to think about how many arguments their function has.
I have some doubts about the effects that will have on inference.
One last solution: somehow define an Arbitrary (Fun a (b -> c))
instance. I have not thought this through but if this makes sense it might be the most elegant solution.
Silly me, we actually do have an instance for functions
Sub Dict :: (Function a, CoArbitrary a, CoArbitrary b, Arbitrary c) :- Arbitrary (Fun a (b -> c))
so we can generate them just fine (arbitrary @(Fun Int (Bool -> Int))
), the problem is showing them!
I am not familiar with the internals of the library, this is my attempt at a Show
instance that curries (it indicates that we would actually need Show (Fun a (b :-> c))
)
-- Doesn't work as intended
instance {-# OVERLAPPING #-} (Show a, Show b, Show c, Function b) => Show (Fun a (b -> c)) where
show = \case
Fun (_, _, False) _ -> "<fun>"
-- ↓ incorrect
Fun (f, _, True) _ -> showFunction (Pair (fmap function f)) Nothing
Any thoughts?
@Icelandjack we can generate and show Fun a (Fun b c)
but that's about the same as Fun (a, b) c
.
I'd like apply2
and apply3
, and the patterns.
Doing trickery is :-1: Maybe it will work with e.g. http://hackage.haskell.org/package/HList-0.4.1.0/docs/Data-HList-HCurry.html#v:hCurry but that functionality could be in a separate package, or at least tried somewhere to prove being useful and unproblematic.
Agreed, I'll make a PR with apply*
, Fn*
but I'd like to leave this open for further discussions