【问题标题】:Checking for a particular data constructor检查特定的数据构造函数
【发布时间】:2011-08-30 15:26:16
【问题描述】:

假设我定义了自己的数据类型,例如

data MyData = A arg| B arg2| C arg3

我将如何编写一个函数(例如:isMyDataType)来检查给定参数是否是MyData 中的特定类型之一,并连续返回一个布尔值(真或假),例如输入 Ghci: isMyDataType B 返回 True,isMyDataType Int 返回 False。

【问题讨论】:

  • Haskell 是静态类型的。这意味着,所有与类型系统相关的问题都将在编译时解决。

标签: haskell types typechecking


【解决方案1】:

Haskell 总是检查类型是否有意义。如果你写了isMyDataType 4,编译器会立即报错,因为4 不是MyData 类型,而是Int 类型。

我不确定这是您要求的,但无论哪种方式,我都强烈建议您在实践中尝试您在此处提出的要求,以便您自己看看。最重要的是你在haskell中查看类型签名,这是学习haskell的关键。

【讨论】:

    【解决方案2】:

    我相信您希望函数测试特定的构造函数

    isA :: MyData -> Bool
    isB :: MyData -> Bool
    

    如果是这样,那么您可以自己编写或导出它们。实现看起来像:

    isA (A _) = True
    isA _     = False
    
    isB (B _) = True
    isB _     = False
    

    要自动派生它们,只需使用 derive 库并在您的源代码中添加:

    {-# LANGUAGE TemplateHaskell #-}
    import Data.DeriveTH
    
    data MyData = ...
        deriving (Eq, Ord, Show}
    
    derive makeIs ''MyData
    -- Older GHCs require more syntax: $( derive makeIs ''MyData)
    

    另请注意:您的数据声明无效,名称必须大写,MyData 而不是myData

    最后,整个答案基于您要测试构造函数的假设,而不是您所说的数据类型(正如 Tarrasch 所说,在编译时静态检查)。

    【讨论】:

    • 是的,我的意思是 TomDM。
    • 是否有更新的答案,因为派生不再在堆栈中?
    • 这个答案早于堆栈。也许你应该在你的项目中添加一个非堆栈包?我知道有办法做到这一点。
    【解决方案3】:

    您可以使用Maybes。您可以创建一组检查每种类型的函数

    getA, getB, getC :: MyData a -> Maybe a
    getA x = case x of {(A v) -> Just v; _ -> Nothing}
    getB x = case x of {(B v) -> Just v; _ -> Nothing}
    getC x = case x of {(C v) -> Just v; _ -> Nothing}
    

    这为某些任务提供了一些实用的习语:

    allAs :: [MyData a] -> [a]
    allAs xs = mapMaybe getA xs
    
    printIfA :: Show a => MyData a -> IO ()
    printIfA x = maybe (return ()) print $ getA x
    

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 2017-11-06
      相关资源
      最近更新 更多