考虑实现on
on f g = curry $ (. bimap g g) $ uncurry f
是什么类型? GHC会说(b -> b -> c) -> (a -> b) -> a -> a -> c
,这是一个很好的猜测。但是它错过了实例on (+) toInteger
。让我们尝试解决该问题(使用RankNTypes
,KindSignatures
,AllowAmbiguousTypes
和ConstraintKinds
):
on :: forall (co :: * -> Constraint) a1 a2 b c .
(co a1, co a2) =>
(b -> b -> c)
-> (forall a . co a => a -> b)
-> a1 -> a2 -> c
然后进行类型检查。但是当我们尝试
> :t (+) `on` toInteger
我们得到
• Couldn't match type ‘c’ with ‘Integer’
‘c’ is untouchable
inside the constraints: co a
bound by a type expected by the context:
forall a. co a => a -> c
at <interactive>:1:1-18
‘c’ is a rigid type variable bound by
the inferred type of it :: (co a1, co a2, Num c) => a1 -> a2 -> c
at <interactive>:1:1
Possible fix: add a type signature for ‘it’
Expected type: a -> c
Actual type: a -> Integer
• In the second argument of ‘on’, namely ‘toInteger’
In the expression: (+) `on` toInteger
那是什么意思?