I suspect that you remember one of these two outcomes:
> :t 1 2 3
1 2 3 :: (Num (t1 -> t -> t2), Num t, Num t1) => t2
> 1 2 3
<interactive>:7:1: error:
• No instance for (Num (t1 -> t0 -> a0)) arising from a use of ‘it’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
The former indicates that Haskell has attempted to interpret the literal 1
as a function that can be applied to the literals 2
and 3
; the Num (t1 -> t -> t2)
constraint says that 1
can be interpreted as a two-argument function, while the Num t
and Num t1
constraints indicate that 2
and 3
can be interpreted as suitable arguments to this function.
The latter indicates the same thing, but goes on to say that furthermore it couldn't find such an instance that tells how to interpret a number as a function.
You can add one if you like; the least you'll need is something like this:
instance Num b => Num (a -> b) where fromInteger = pure . fromInteger
(This leaves the other Num
methods undefined, meaning they will throw an error if you try to use them at function type.)
Following that declaration, the above two queries have slightly different results:
> :t 1 2 3
1 2 3 :: Num t => t
> 1 2 3
1
The former indicates that since there is now an in-scope method of interpreting number literals as functions, we can collapse all the previous constraints quite a bit. The latter produces a number "by accident" as it were: the monomorphism restriction defaults the polymorphic type Num t => t
to Integer
and prints the result.
The story with (:)
is similar, I expect: probably you remember asking a :t
query, which works just fine:
> :t (:)
(:) :: a -> [a] -> [a]
There's no standard way built-in of printing functions, though, so trying to "run" (:)
on its own produces an error:
> (:)
<interactive>:14:1: error:
• No instance for (Show (a0 -> [a0] -> [a0]))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
This error says basically what I did: by default there's no way of showing functions. As before, you can add one if you like; a popular but lossy one is this:
> :m + Text.Show.Functions
> (:)
<function>
Slightly less lossy would be to do this instead (not in addition!):
> :m + Data.Typeable
> instance (Typeable a, Typeable b) => Show (a -> b) where show = show . typeOf
...but you can't apply it to (:)
directly, as it works only with monomorphic functions.
> (:) 3
[Integer] -> [Integer]
Of course, the best is to use a lossless show implementation, but it is even more restrictive on which functions it can be used with: only monomorphic functions (as before) with finite domain (new restriction).
> :m + Data.Universe.Instances.Reverse
> enumFrom
[((),[()])]