notes-computer-programming-programmingLanguageDesign-prosAndCons-returnTypeOnlyPolymorphism

in Haskell this is confusing: http://stackoverflow.com/questions/3467279/how-to-create-a-polyvariadic-haskell-function

i'm not sure exactly what i want here. i consider this abuse of the type system but by what criteria?

One could say: if there is an expression containing subexpressions which are equivalent to the same function given the same type of input, then they should be the same type. But this would pretty much rule polymorphism only on the return type, because you could have a long program as one expression with different uses of the same function in very different places. Not sure if that is a big sacrifice or not: see http://programmers.stackexchange.com/questions/105662/is-return-type-only-polymorphism-in-haskell-a-good-thing

In there, my interpretation of what Philip JF points out is that if you have values that are union types, then that's not too different from 0-ary functions which return different types, since in Haskell 0-ary functions aren't distinct from their return values. So it would seem inconsistent to disallow non-0-ary functions from doing that while allowing 0-ary functions to.

Some potential responses that i can think of:

however, http://programmers.stackexchange.com/questions/105662/is-return-type-only-polymorphism-in-haskell-a-good-thing suggests that this is related to Haskell's monomorphism restriction ( http://www.haskell.org/haskellwiki/Monomorphism_restriction , http://www.haskell.org/onlinereport/decls.html#monomorphism). Perhaps while fixing this we want to remove enough power to make the monomorphism restriction irrelevant. I'm not sure that http://programmers.stackexchange.com/questions/105662/is-return-type-only-polymorphism-in-haskell-a-good-thing is correct about it being tied to polymorphic-return-only types, though.

actually, some of these responses won't work; consider a fn sumOf2 which has a polymorphic form which takes pairs of inputs (a,b).

Now do

sumOf2 x = sumOf (x,b) sumOf2 5 8 22 b 5 8 22 :: int

i'm not sure if that that is quite right but i bet you can fix it somehow. The point is, to make the backwards type system inference produce a value b whose type contains the forbidden information from the future that we dont want sumOf to polymorph on, and then to feed that b to sumOf as an input, so that it uses input polymorphism, not return polymorphism, to utilize the forbidden information.

another idea is to limit polymorphism as follows: the function signature for all of the polymorphic forms must be a (single) template. You can still get ad-hoc in the implementation.

umm, no dude, that isn't good enough, the offending example already meets this:

class SumRes? r where sumOf :: Integer -> r

instance SumRes? Integer where sumOf = id

instance (Integral a, SumRes? r) => SumRes? (a -> r) where sumOf x = sumOf . (x +) . toInteger

hmm.. the problem seems to be that one of the instances demands a higher kind and the other doesnt. But if you forbade this, could someone get around it by just wrapping the higher kind in an opaque wrapper type like IsAFunction??

hmm.. no, the offending example doesnt quite meet this; should require that in each function in the class, no type parameters appear that didnt appear in the inputs to that function.

but, as noted above, you could get around this by giving a dummy argument to the fun (e.g. sumOf(dummy)) so that the compiler can infer 'dummy' to be the desired return type

see jasperType.txt for current best guess