Last active
May 12, 2020 14:23
-
-
Save szabi/412c88f7ad383c1c3a1704f6642eec72 to your computer and use it in GitHub Desktop.
Could not deduce <instance> arising from...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Angle where | |
{- | Type-class for angle units. | |
This library provides @Rad@ (radians) and @Deg@ (degrees), but you could | |
define e.g. Gon. The instance definition takes the value of a turn. | |
-} | |
class Angle a where | |
-- how many UNITS does a whole turn have? | |
turn :: Floating x => a x | |
-- normalizes the angle | |
norm :: (RealFrac x, Floating x) => a x -> a x | |
norm x = wrap $ (un x) - (un turn) * (fromIntegral . floor ) ( (un x) / (un turn)) | |
-- automatic conversion for | |
toRad :: Floating x => a x -> Rad x | |
toRad = Rad . toRad' | |
toRad' :: Floating x => a x -> x | |
toRad' x = (un x) / (un turn) * 2 * pi | |
fromRad :: Floating x => Rad x -> a x | |
fromRad x = wrap $ (un turn) * (unRad x / 2 / pi) | |
-- technical to be able to refer to construct and deconstruct the values | |
-- in the default definitions | |
un :: a x -> x | |
wrap :: x -> a x | |
{-# MINIMAL turn, un, wrap #-} | |
{- | An angle in radians. @Rad@ is provided by this library and is used | |
internally to define default implementations for arbitrary units. | |
-} | |
newtype Rad x = Rad { unRad :: x } deriving (Eq, Ord, Show) | |
instance Angle Rad where | |
un = unRad | |
wrap = Rad | |
turn = Rad (2 * pi) | |
-- we specialize toRad and fromRad here | |
toRad = id | |
toRad' = unRad | |
fromRad = id | |
-- | An angle in degrees. | |
newtype Deg x = Deg { unDeg :: x } deriving (Eq, Ord, Show) | |
instance Angle Deg where | |
un = unDeg | |
wrap = Deg | |
turn = Deg 360 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
src/Angle.hs:12:30-36: error: | |
• Could not deduce (Angle a0) arising from a use of ‘un’ | |
from the context: Angle a | |
bound by the class declaration for ‘Angle’ | |
at src/Angle.hs:7:8-12 | |
or from: (RealFrac x, Floating x) | |
bound by the type signature for: | |
norm :: forall x. (RealFrac x, Floating x) => a x -> a x | |
at src/Angle.hs:11:15-53 | |
The type variable ‘a0’ is ambiguous | |
These potential instances exist: | |
instance Angle Deg -- Defined at src/Data/Angle.hs:46:10 | |
instance Angle Rad -- Defined at src/Data/Angle.hs:35:10 | |
• In the first argument of ‘(*)’, namely ‘(un turn)’ | |
In the second argument of ‘(-)’, namely | |
‘(un turn) * (fromIntegral . floor) ((un x) / (un turn))’ | |
In the second argument of ‘($)’, namely | |
‘(un x) - (un turn) * (fromIntegral . floor) ((un x) / (un turn))’ | |
| | |
12 | norm x = wrap $ (un x) - (un turn) * (fromIntegral . floor ) ( (un x) / (un turn)) | |
| ^^^^^^^ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am perplexed by the error message. I assumed when compiling line 12, GHC would simply refer to the definition of
turn
in line 9. This seems straightforward and the types are compatible, but GHC seems to insist to check for concrete instances instead of the type in the class definition when type checking and deferring resolution until later.