简体   繁体   English

在 Haskell 中打印自定义数据类型

[英]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我试图在 haskell 中学习类型类,但在表示和打印自定义数据类型类时遇到问题

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我得到的Data constructor not in scope: TrafficLight :: TrafficLight -> t

TrafficLight is name of your type. TrafficLight是您的类型名称。

Red , Yellow , Green are constructors. RedYellowGreen是构造函数。

You don't have data constructor with name TrafficLight .您没有名称为TrafficLight数据构造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 .一种名为TrafficLight的新类型

  • Three constructors for that type, called Red , Yellow and Green .该类型的三个构造函数,称为RedYellowGreen 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.构造函数本身可以看作是包含数据类型的n 元函数(在这种情况下没有包含的数据,所以构造函数是“空的”——换句话说,根本不是函数)到你的类型定义。 Ie 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 .) (通常,例如对于data Foo = Quz Int | Ruz Char Bool ,它将是Quz :: Int -> FooRuz :: 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.您似乎很困惑,因为在例如 C++ 或 Python 中,构造函数的调用名称与您定义的类(以及类型)相同,但在 Haskell 中,构造函数可以与类型相同,也可以不同。 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 .然后要在当前数据类型中生成对应于Red的值,您可以编写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与 Haskell 的多构造函数类型类似的 OO 是具有特定数量子类的抽象基类,例如

    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 .这将允许您使用例如Red()并获得可用作TrafficLight类型值的值。
    (In Python, the typing relationships are of course somewhat meaningless...) (在 Python 中,类型关系当然有点无意义......)
    (Yes, I know Python also has Enum types which solve this particular problem better.) (是的,我知道 Python 也有 Enum 类型可以更好地解决这个特定问题。)

  • A Show instance, like you could also write separately一个Show实例,就像你也可以单独写一样

    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因为RedYellowGreen实际上是TrafficLight类型的值, TrafficLight您可以像在源文件或 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. ...但没有意义的是直接在值级代码中使用名称TrafficLight

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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