I recently came across this weird issue in Haskell. The following code is supposed to return a value trimmed down to a range (if it's above high
it should return high
if it's under low
it should return low
.
inRange :: Int -> Int -> Int -> Int
inRange low high = max low $ min high
the error message is:
scratch.hs:2:20:
Couldn't match expected type ‘Int -> Int’ with actual type ‘Int’
In the expression: max low $ min high
In an equation for ‘inRange’: inRange low high = max low $ min high
scratch.hs:2:30:
Couldn't match expected type ‘Int’ with actual type ‘Int -> Int’
Probable cause: ‘min’ is applied to too few arguments
In the second argument of ‘($)’, namely ‘min high’
In the expression: max low $ min high
Shouldn't it take another argument and put it into high? I already tried other possibilities like:
\x -> max low $ min high x
and
\x -> max low $ (min high x)
When trying it in GHCI I'm getting the following error:
<interactive>:7:5:
Non type-variable argument in the constraint: Num (a -> a)
(Use FlexibleContexts to permit this)
When checking that ‘inRange’ has the inferred type
inRange :: forall a.
(Num a, Num (a -> a), Ord a, Ord (a -> a)) =>
a -> a
($)
is defined as:
f $ x = f x
So your example actually is:
max low (min high)
which is wrong, because you actually want
max low (min high x)
Using function composition, which is defined as:
f . g = \x -> f (g x)
and your working example \x -> max low (min high x)
we get:
\x -> max low (min high x)
== max low . min high -- by definition of (.)