Reputation: 41
In Haskell, I just know that
:type ((+)(1))
((+)(1)) :: Num a => a -> a
((+)(1) 2
3
But how about
:type abs(sqrt)
abs(sqrt) :: (Floating a, Num (a -> a)) => a -> a
Actually, I try many times but fail to use the function 'abs(sqrt)'. Then I have a few questions. What is the type(class?) '(Floating a, Num (a -> a))'? Is it possible to use the function 'abs(sqrt)'? How?
Upvotes: 2
Views: 179
Reputation: 101
Good answer. Your answer solved my confusion, and I have implement an Num(a->a)
, which truly doesn't make sense, but can be truly be executed, thanks for your explanation which triggered me to do this.
instance Num ( Integer -> Integer ) where
(+) = \x y -> fmap x y
negate = undefined
(*) = undefined
abs = undefined
signum = undefined
fromInteger = undefined
Load it into ghci and see the result.
ghci> :t (+1) + (+2)
(+1) + (+2) :: (Num a, Num (a -> a)) => a -> a
ghci> (+1) + (+2) $ 3
6
Upvotes: 0
Reputation: 9930
It is probably not possible to use this function.
What's likely happening here is that the type is saying that abs(sqrt)
has the constraints that a
must be of type class Floating
and (a -> a)
must be of type class Num
. In other words, the sqrt
function needs to be able to be treated as if it was a number.
Unfortunately, sqrt
is not of type class Num
so there won't be any input that will work here (not that it would make sense anyway). However, some versions of GHCi allow you to get the type of as if it were possible.
Have a look at Haskell type length + 1 for a similar type problem.
As ErikR has said, perhaps you meant to write abs . sqrt
instead.
Upvotes: 1
Reputation: 54058
A type class is a way to generalize functions so that they can be polymorphic and others can implement those functions for their own types. Take as an example the type class Show
, which in a simplified form looks like
class Show a where
show :: a -> String
This says that any type that implements the Show
typeclass can be converted to a String
(there's some more complication for more realistic constraints, but the point of having Show
is to be able to convert values to String
s).
In this case, the function show
has the full type Show a => a -> String
.
If we examine the function sqrt
, its type is
> :type sqrt
sqrt :: Floating a => a -> a
And for abs
:
> :type abs
abs :: Num b => b -> b
If you ask GHCi what the types are it will use the type variable a
in both cases, but I've used b
in the type signature for abs
to make it clear that these are different type variables of the same name, and it will help avoid confusion in the next step.
These type signatures mean that sqrt
takes a value whose type implements the Floating
typeclass (use :info Floating
to see all the members) and returns a value of that same type, and that the abs
function takes a value whose type implements the Num
typeclass and returns a value of that same type.
The expression abs(show)
is equivalently parsed as abs sqrt
, meaning that sqrt
is the first and only argument passed to abs
. However, we just said that abs
takes a value of a Num
type, but sqrt
is a function, not a number. Why does Haskell accept this instead of complaining? The reason can be seen a little more clearly when we perform substitution with the type signatures. Since sqrt
's type is Floating a => a -> a
, this must match the argument b
in abs
's type signature, so by substituting b
with Floating a => a -> a
we get that abs sqrt :: (Floating a, Num (a -> a)) => a -> a
.
Haskell actually allows the function type to implement the Num
typeclass, you could do it yourself although it would likely be nonsensical. However, just because something wouldn't seem to make sense to GHC, so long as the types can be cleanly solved it will allow it.
You can't really use this function, it just doesn't really make sense. There is no built-in instance of Num (a -> a)
for any a
, so you'd have to define your own. You can, however, compose the functions abs
and sqrt
using the composition operator .
:
> :type abs . sqrt
abs . sqrt :: Floating c => c -> c
And this does make sense. This function is equivalent to
myfunc x = abs (sqrt x)
Note here that x
is first applied to sqrt
, and then the result of that computation is passed to abs
, rather than passing the function sqrt
to abs
.
Upvotes: 2
Reputation: 52039
When you see Num (a -> a)
it generally means you made a mistake somewhere.
Perhaps you really wanted: abs . sqrt
which has type Floating c => c -> c
- i.e. it's a function of a Floating type (e.g. Float, Double) to the same Floating type.
Upvotes: 3