简体   繁体   中英

Printing custom data type in haskell

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM