Skip to content

Instantly share code, notes, and snippets.

@rentalcustard
Last active August 29, 2015 14:04
Show Gist options
  • Save rentalcustard/c1c3872933856d63be44 to your computer and use it in GitHub Desktop.
Save rentalcustard/c1c3872933856d63be44 to your computer and use it in GitHub Desktop.
Type problems
numberwang :: (Floating a) => a -> a -> String
numberwang x y
| x / y ^ 2 <= 18.5 = "a"
| x / y ^ 2 <= 25.0 = "b"
| x / y ^ 2 <= 30.0 = "c"
| otherwise = "d"
-- gives
Prelude> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
baby.hs:14:15:
Could not deduce (Ord a) arising from a use of `<='
from the context (Floating a)
bound by the type signature for
numberwang :: Floating a => a -> a -> String
at baby.hs:12:15-46
Possible fix:
add (Ord a) to the context of
the type signature for numberwang :: Floating a => a -> a -> String
In the expression: x / y ^ 2 <= 18.5
In a stmt of a pattern guard for
an equation for `numberwang':
x / y ^ 2 <= 18.5
In an equation for `numberwang':
numberwang x y
| x / y ^ 2 <= 18.5 = "a"
| x / y ^ 2 <= 25.0 = "b"
| x / y ^ 2 <= 30.0 = "c"
| otherwise = "d"
Failed, modules loaded: none.
-- I can understand this, I think; Floating doesn't conform to Ord. Which seems weird, but ok. Let's try Float?
numberwang :: (Float a) => a -> a -> String
numberwang x y
| x / y ^ 2 <= 18.5 = "a"
| x / y ^ 2 <= 25.0 = "b"
| x / y ^ 2 <= 30.0 = "c"
| otherwise = "d"
-- Gives:
Prelude> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
baby.hs:12:13:
`Float' is applied to too many type arguments
In the type signature for `bmiTell':
bmiTell :: Float a => a -> a -> String
Failed, modules loaded: none.
-- I don't understand this error at all.
-- Magically, this works. What's the difference?
numberwang :: (RealFloat a) => a -> a -> String
numberwang x y
| x / y ^ 2 <= 18.5 = "a"
| x / y ^ 2 <= 25.0 = "b"
| x / y ^ 2 <= 30.0 = "c"
| otherwise = "d"
@rentalcustard
Copy link
Author

Ah! I can't use types as constraints. So I can fix it like this:

numberwang :: (Ord a) => (Fractional a) => a -> a -> String                                                                                                                                                                                    
numberwang x y                                                                                                                                                                                                                                 
  | x / y ^ 2 <= 18.5 = "a"                                                                                                                                                                                                                    
  | x / y ^ 2 <= 25.0 = "b"                                                                                                                                                                                                                    
  | x / y ^ 2 <= 30.0 = "c"                                                                                                                                                                                                                    
  | otherwise = "d"       

Or like this:

numberwang :: Float -> Float -> String                                                                                                                                                                                                         
numberwang x y                                                                                                                                                                                                                                 
  | x / y ^ 2 <= 18.5 = "a"                                                                                                                                                                                                                    
  | x / y ^ 2 <= 25.0 = "b"                                                                                                                                                                                                                    
  | x / y ^ 2 <= 30.0 = "c"                                                                                                                                                                                                                    
  | otherwise = "d"   

@leocassarani
Copy link

You can collapse multiple typeclass constraints together like so:

numberwang :: (Ord a, Fractional a) => a -> a -> String

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment