【问题标题】:Haskell: Pattern matching with custom data typesHaskell:与自定义数据类型匹配的模式
【发布时间】:2019-07-08 01:37:35
【问题描述】:

我有以下自定义数据类型:

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) 

假设我有一个如下形式的元组:

let x = ("Jump", R 90)

我使用以下方法提取元组中的第二个值:

snd x = R 90

有什么方法可以使用模式匹配从 R 90 中获取 Rotation 值 90,以便我可以在另一个代码区域中使用它?当我使用snd x 时,结果的类型是 Special 类型,但我只想获取 Rotation 值。任何见解都值得赞赏。

【问题讨论】:

  • case snd x of R n -> ...?
  • let (R rotation) = snd x in ...

标签: haskell functional-programming pattern-matching


【解决方案1】:

RSpecial 数据类型的构造函数。为了从R 中提取Rotation,您需要编写以下函数:

unsafeExtractRotation :: Special -> Rotation
unsafeExtractRotation (R rotation) = rotation

然而,这个函数是不安全的(顾名思义),因为它是部分的:它不能处理所有情况。根据函数类型,它应该与 Special 数据类型的任何值一起使用,因此可以将 L 构造函数传递给此函数,它会崩溃,以后很难弄清楚此类错误的来源。

更安全的函数可以如下所示:

extractRotation :: Special -> Maybe Rotation
extractRotation (R rotation) = Just rotation
extractRotation _ = Nothing

它不会崩溃。相反,它会强制您明确处理传递不同构造函数的情况。

【讨论】:

    【解决方案2】:

    根据您提供的信息,我可以提出三个想法,一个来自 Shersh,但您可以使用更适合您的代码的一个:

    -- If is not of Rotation type, value is 0
    specialToRotation (R n) = n
    specialToRotation _     = 0
    
    -- If not of Rotation type, pattern matching failure
    specialToRotation2 (R n) = n
    
    -- If not of Rotation type, value is Nothing
    
    specialToRotation3 (R n) = Just n
    specialToRotation3 _     = Nothing
    

    选项 2) 并不完全错误,很多功能在 Haskell 中是部分的,请从 list api 中考虑 headtail。两者都没有空列表的定义。所以也许你可以使用它。

    【讨论】:

    • #3 包含 #1 和 #2:分别为 fromMaybe 0 . specialToRotation3fromJust . specialToRotation3
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多