
On May 20, 2010, at 3:18 AM, Brent Yorgey wrote:
On Wed, May 19, 2010 at 04:27:14AM +0000, R J wrote:
What are some simple functions that would naturally have the following type signatures: f :: (Integer -> Integer) -> Integer
Well, this means f is given a function from Integer to Integer, and it has to somehow return an Integer, (possibly) using the function it is given. For example, f could just ignore its argument:
f _ = 6
That would NOT give f the right type. The type would be f :: Num r => a -> r
Or it could apply it to a particular input value:
f g = g 0
That would NOT give f the right type. The type would be f :: Num a => (a -> b) -> b
I'll let you think of some other possibilities.
The key point is the 'that would NATURALLY have', which I take to mean "as a result of type inference without any forcibly imposed type signatures". What kind of definition of f, *not* including "::" anywhere, would result in Haskell inferring the desired signature? The key thing is that the types *must* be fully constrained to Integer. The simplest way to get something that is guaranteed to be the specific type Integer, as far as I can see, is to use something like "toInteger 0". If we have identityForA :: A -> A identityForB :: B -> B then we can constrain a variable x to A using identityForA $ x and we can constrain a variable g to A->B using identityForB . g . identityForA. This is, in a sense, equivalent to providing a type signature, but it meets the formal requirements of these questions. identityForInteger = (+ toInteger 0) is an example. f g = g z + z where z = toInteger 0 does the trick here. m% ghci Prelude> let f g = g z + z where z = toInteger 0 Prelude> :type f f :: (Integer -> Integer) -> Integer