рассмотрим эту реализацию 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
Так что это значит?