在haskell中,ADT有一个常见的习惯用法,例如:
data MyData a = X a | Y a | Z a
...定义函数:
isX (X _) = True
isX _ = False
isY (Y _) = True
isY _ = False
isZ (Z _) = True
isZ _ = False
有没有办法自动生成这些功能?
动机:这可以说是惯用的,或者不是惯用的haskell,取决于你问的人......标准库本身有isJust
,isNothing
。
扩展问题的范围,记录语法允许您为数据类型创建函数:
data MyData = A { a1 :: Type1, a2 :: Type2 } | B { b1 :: Type3, b2 :: Type4 }
这些功能有以下类型:
a1 :: MyData -> Type1
a2 :: MyData -> Type2
b1 :: MyData -> Type3
b2 :: MyData -> Type4
虽然这对于只有1个构造函数的数据类型来说无疑是很好的,但对于具有多于1个构造函数的数据类型来说则更少,因为当使用了错误的构造函数时,自动生成的函数会导致错误。
有没有办法自动生成这些类型的函数?
a1 :: MyData -> Maybe Type1
a2 :: MyData -> Maybe Type2
b1 :: MyData -> Maybe Type3
b2 :: MyData -> Maybe Type4
答案 0 :(得分:4)
这种模式是个坏主意。它会导致容易出错的代码。但是,有一种更好的方法,也包括这种机制,并积极回答你的问题。使用Prisms。您可以使用Template Haskell automatically derive使用它们。然后你可以使用is
来获得你想要的东西,但是,你仍然不应该在正常情况下。尽管如此,通过提供棱镜,您的用户可以使用更好的方法,同时在更方便时仍可访问is
。
最终结果是像
这样的代码data MyData a = X a | Y a | Z a
makePrisms ''MyData
filterX = filter (is _X)