haskell - Tricky type signature for pairs of reversed pairs -


lets have following data type:

data d b = d (a,b) (b,a) 

and want define following function on it:

apply f (d x y) = d (f x) (f y) 

what type signature of apply?

here examples of f okay:

f :: -> -- ok f :: (a, b) -> (b, a) -- ok f :: (a, b) -> ((a, c), (b, c)) -- ok 

in of above cases, end valid type d.

but not okay:

f :: (a, b) -> (a, a) 

because when send such function through apply end having attempt construct d (a,a) (b,b) not valid unless a = b.

i can't seem work out type signature express this? also, in general, there way ghc tell me these signatures should be?

typed holes edit:

in attempt find type using typed holes, tried following:

x = apply _ (d (1::int,'a') ('b',2::int)) 

and got:

found hole ‘_’ type: (int, int) -> (b, b) where: ‘b’ rigid type variable bound            inferred type of x :: d b b 

which seems me nonsense f :: (int, int) -> (b, b) not going work here.

multiple types fit apply, inferred ((t, t) -> (b, b)) -> d t t -> d b b sensible , usable one. alternatives going higher-rank, let's enable language extension:

{-# language rankntypes #-} 

first, can make apply id work:

apply :: (forall a. -> a) -> d b -> d b apply f (d x y) = d (f x) (f y) 

however, id only function apply works (all total functions of type forall a. -> a equal id).

here's type:

apply :: (forall a. -> (c, c)) -> d b -> d c c apply f (d x y) = d (f x) (f y) 

but comes @ price. f-s can constant functions ignore previous fields of d. apply (const (0, 0)) works, have no way inspect argument of f.

in contrast, inferred type pretty useful. can express transformations @ actual data contained in d.

at point, might ask: why ghc infer infers? after all, functions work alternative types, don't work default type. better infer higher-ranked types? well, such types extremely useful, inferring them unfeasible.

type inference rank-2 types rather complicated, , not practical either, because it's not possible infer most general types. rank-1 inference, can infer type more general other valid types same expression. there's no such guarantee rank-2 types. , inference rank-3 , above types undecidable.

for these reasons, ghc sticks rank-1 inference, never infers types forall-s inside function arguments.


Comments