I was trying to learn type classes in haskell and have trouble representing and printing custom data type classes
Here's what I tried, my goal is to print the value.
data TrafficLight = Red | Yellow | Green deriving(Show)
instance Eq TrafficLight where
Red == Red = True
_ == _ = False
main = do
print x
print y
print z
where
x = (TrafficLight Red)
y = (TrafficLight Red == TrafficLight Red)
z = (TrafficLight Red == TrafficLight Yellow)
I'm getting Data constructor not in scope: TrafficLight :: TrafficLight -> t
TrafficLight
is name of your type.
Red
, Yellow
, Green
are constructors.
You don't have data constructor with name TrafficLight
.
FIX:
x = Red
y = (Red == Red)
z = (Red == Yellow)
The line
data TrafficLight = Red | Yellow | Green deriving(Show)
defines three different things at once:
A new type called TrafficLight
.
Three constructors for that type, called Red
, Yellow
and Green
. A constructor itself can be seen as an n -ary function from the contained data types (in this case there is no contained data, so the constructors are “nullary” – in other words, not functions at all) to the type you're defining. Ie
Red :: TrafficLight Yellow :: TrafficLight Green :: TrafficLight
(In general, eg for data Foo = Quz Int | Ruz Char Bool
, it would be Quz :: Int -> Foo
and Ruz :: Char -> Bool -> Foo
.)
You seem to be confused because in eg C++ or Python, constructors are invoked with the same name as the class (and thus type) you're defining, but in Haskell constructors can either be called the same as the type, or different. By convention, if there's just a single constructor it tends to be called the same as the type, if there are multiple constructors they're all called different. For example, if you had defined
data TrafficLight' = TrafficLight' { redLightOn :: Bool , yellowLightOn :: Bool , greenLightOn :: Bool }
then to generate a value corresponding to Red
in your current data type, you would write TrafficLight' True False False
.
An OO analogue to Haskell's multi-constructor types would be an abstract base class with a specific number of child classes, like
class TrafficLight: # could inherit `abc.ABC` to make it pass # explicitly abstract class Red(TrafficLight): def __init__(self): pass class Yellow(TrafficLight): def __init__(self): pass class Green(TrafficLight): def __init__(self): pass
which would allow you to use eg Red()
and get a value that can be used as a value of type TrafficLight
.
(In Python, the typing relationships are of course somewhat meaningless...)
(Yes, I know Python also has Enum types which solve this particular problem better.)
A Show
instance, like you could also write separately
instance Show TrafficLight where show = ...
Because Red
, Yellow
and Green
are actually values of type TrafficLight
, you can simply use them like that in your source file or at the REPL
Prelude> data TrafficLight = Red | Yellow | Green deriving(Show)
Prelude> Red
Red
You could also add a local signature within a bigger expression
Prelude> (Red :: TrafficLight, 37)
(Red,37)
...but what doesn't make sense is use the name TrafficLight
directly in value-level code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.