【问题标题】:Haskell: Understanding custom data typesHaskell:了解自定义数据类型
【发布时间】:2019-07-07 13:21:24
【问题描述】:

我正在尝试在 Haskell 中创建自己的自定义数据类型。

我有以下数据类型:

type Length = Integer 
type Rotation = Integer 
data Colour = Colour { red, green, blue, alpha :: Int }
            deriving (Show, Eq)

我正在尝试创建可以是上述任一数据类型的自定义数据类型。我有以下内容:

data Special 
  = L Length 
  | R Rotation 
  | Col Colour  
  deriving (Show, Eq) 

但是,如果我有 Special 数据类型的实例,我希望能够提取 LengthRotationColour 值。

如果我有:

L length

这里的lengthSpecial 类型还是Length 类型?如果lengthSpecial 类型,有没有办法提取它,所以它是Length 类型?

例如,下面的代码是否有效?

takeL (x:xs)
      | x == (L length) = length

感谢任何见解。

【问题讨论】:

  • “提取价值”是什么意思?这就是所谓的“总和类型”——因此它由这些类型中的一个值 组成,而不是它们的集合。具体来说,一个元素可能是L 1R 42——它们都不能从中提取Colour。您可能想要一个“产品类型”,即data Special = Special Length Rotation Colour - 该类型的每个值都有可以提取的LengthRotationColour 值。
  • 你可以解压数据构造函数。
  • @RobinZigmond 我不希望数据类型是产品数据类型,因为我希望 Special 是长度、旋转或颜色之一。
  • @ceno980 - 感谢您的澄清,在这种情况下,您的类型确实是正确的。但在这种情况下,不清楚您所说的“提取”是什么意思,因为每个值只能提取三个组件中的 一个。如果您想匹配它使用的构造函数之一,您可以使用模式匹配或case 表达式来做到这一点。关于您最近的编辑,在表达式 L length 中,length 必须是 Length(即 Integer),这取决于您如何定义构造函数。

标签: haskell functional-programming pattern-matching algebraic-data-types custom-data-type


【解决方案1】:

要使表达式 L length 有效,length 必须是 Length(因为 L :: Length -> Special)。

takeL (x:xs)
      | x == (L length) = length

无效。除非你在某处重新定义了length,否则length 是标准库中的函数[a] -> Int,所以L length 是一个类型错误。

我认为您在这里尝试做的只是模式匹配:

takeL (L length : xs) = length

【讨论】:

    【解决方案2】:

    数据类型定义

    data Special  = 
    

    读取:Special 是一个新的类型,以便创建Special 类型的

                      L Length 
    
    • 调用L l,其中lLength 类型的值;或

                  | R Rotation 
      
    • 调用R r,其中rRotation 类型的值;或

                  | Col Colour  
      
    • 调用Col c,其中cColour 类型的值。


    要分析Special 类型的值,需要考虑三种情况:

    foo :: Special -> ...
    foo val = 
        case val of
            L   l -> ...  
    
    • lLength 类型的值,在这种情况下val 实际上是L l;或

          R   r -> ... 
      
    • rRotation 类型的值,在这种情况下val 实际上是R r;或

          Col c -> ...  
      
    • cColour 类型的值,在这种情况下 val 实际上是 Col c

    函数定义中的case语法也可以用基于模式的子句来表达:

    foo :: Special -> ...
    foo (L   l) = ...
    foo (R   r) = ...
    foo (Col c) = ...
    

    【讨论】:

      猜你喜欢
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-05
      • 2016-06-01
      • 2012-03-12
      • 1970-01-01
      • 2014-08-05
      相关资源
      最近更新 更多