简体   繁体   English

在 Haskell 中打印我自己的数据类型的自定义表示

[英]Printing a custom representation of my own datatype in Haskell

Context语境

Important detail, I am using Haskell (NOT CABAL) on repl.it .重要的细节,我在 repl.it 上使用Haskell (不是 CABAL)。 I would like to print a custom Haskell datatype that I created.我想打印我创建的自定义 Haskell 数据类型。 I was thinking of an approach similar to Python's __repr__ or __str__ methods, when creating a new class. Something like:在创建新的 class 时,我正在考虑一种类似于 Python 的__repr____str__方法的方法。类似于:

class Length:
    def __init__(self, value, unit_of_measurement):
        self.value = value
        self.unit_of_measurement = unit_of_measurement
    def __str__(self):
        return f'{self.value}{self.unit_of_measurement}'
    def __repr__(self):
        return self.__str__()

Which will produce the following:这将产生以下内容:

>>> # I can print a custom representation of the object
>>> l = Length(10, 'cm')
>>> l
10cm
>>> print(l)
10cm

The problem问题

I am trying to instantiate the Show class in my custom datatype and use pattern matching to customize the output that will be sent to the console.我正在尝试在我的自定义数据类型中实例化Show class 并使用模式匹配来自定义将发送到控制台的 output。

What I tried so far到目前为止我尝试了什么

-- This works fine
data Length = Length {value :: Double, unit_of_measurement :: String}
    deriving (Eq, Ord)  -- I don't want to use default Show inheritance

-- These lines are actually wrong, but I don't know how to solve this
-- Also, how to get the fields declared in my datatype???
instance Show Length where  -- Or IO, I am not sure
    print Length = print $ show value ++ unit_of_measurement

Ignoring the wrong lines that I mentioned (so the compiler won't stop the execution) and considering I have used Haskell's built-in inheritance mechanism with Show ( deriving(Show) ) this will be the result, (which I don't like):忽略我提到的错误行(因此编译器不会停止执行)并考虑到我已经使用 Haskell 的内置 inheritance 机制Show ( deriving deriving(Show) ) 这将是结果,(我不喜欢):

λ> :load Main.hs
[1 of 1] Compiling Main             ( Main.hs, interpreted )
Ok, one module loaded.
λ> let test = Length 10 "cm"
λ> test
Length {value = 10.0, unit_of_measurement = "cm"}  -- HERE 😤, THIS IS THE PROBLEM

I understand if it is not possible to do exactly what I want, but, is there any way to do something near this, or similar?我知道是否不可能完全按照我的意愿去做,但是,有什么办法可以做到这一点或类似的事情吗? Thanks in advance!提前致谢!

The method of the Show typeclass is called show , not print . Show类型类的方法称为show ,而不是print You'll need to remove the call to print .您需要删除对print的调用。 The show function must return a plain String , not an IO () . show function 必须返回一个普通的String ,而不是IO ()

To pattern match on a record as you have it, you can enable the RecordWildCards language extension by declaring it at the very top of the file, and then in the function definition use Length{..} to pattern match and bring all the fields of the record into scope.要在记录上进行模式匹配,您可以通过在文件的最顶部声明它来启用RecordWildCards语言扩展,然后在 function 定义中使用Length{..}进行模式匹配并带来所有字段记录成scope。

{-# LANGUAGE RecordWildCards #-}

data Length = Length {value :: Double, unit_of_measurement :: String}
    deriving (Eq, Ord)

instance Show Length where
    show Length{..} = show value ++ unit_of_measurement

Without that language extension, you could access the record fields in a few other ways:如果没有该语言扩展,您可以通过其他几种方式访问记录字段:

show Length{value=v, unit_of_measurement=u} = show v ++ u

show (Length v u) = show v ++ u

show l = show (value l) ++ unit_of_measurement l

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

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