【问题标题】:Haskell: automatic creation of constuctor-checker / selector functionsHaskell:自动创建构造函数检查器/选择器函数
【发布时间】:2016-02-07 21:28:33
【问题描述】:

在 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,这取决于你问谁......标准库本身有isJustisNothing

扩展问题的范围,记录语法允许您为数据类型创建函数:

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 个构造函数的数据类型无疑是非常有用的,但对于具有多个构造函数的数据类型来说就不是这样了,因为当使用了错误的构造函数时,自动生成的函数会导致错误。

有没有办法用这些类型自动生成函数?

a1 :: MyData -> Maybe Type1
a2 :: MyData -> Maybe Type2
b1 :: MyData -> Maybe Type3
b2 :: MyData -> Maybe Type4

【问题讨论】:

  • 为什么要这样的功能? IMO 这是单调的。 布尔盲。直接匹配你需要的构造函数,这就是 Haskell 的方式。
  • 首先想到的是 TemplateHaskell(嗯......) - 但我同意 @leftaroundabout
  • 这是您的法定警告,因为 ADT 代表“代数数据类型”和“抽象数据类型”,所以它是一个值得避免的首字母缩略词。同时,检查器和选择器将前者视为后者的症状。
  • 感谢 cmets!我已经扩展了我的问题......
  • 我不同意上面的 cmets:这些函数完全没问题,尤其是选择器。在不需要时避免“布尔盲”是一种反反模式(参见this)。

标签: haskell


【解决方案1】:

这种模式是个坏主意。它会导致容易出错的代码。但是,有一种更好的方法也包括此机制并积极回答您的问题。使用Prisms。您可以使用 Template Haskell automatically derive 他们。然后你可以使用is 来获得你想要的东西,但是,在正常情况下你仍然不应该。尽管如此,通过提供棱镜,您的用户可以使用更好的方法,同时仍然可以在更方便的时候访问is

最终结果是这样的代码

data MyData a = X a | Y a | Z a
makePrisms ''MyData

filterX = filter (is _X)

【讨论】:

  • 谢谢,这很有用!我已经扩展了我的问题......如果你也能解决这个问题,我将不胜感激。
  • 请参阅this unanswered question 了解有关此问题的一些讨论。您可以使用declarePrisms 立即获得大部分方法,您可以使用一些元组镜头进行组合以获取遍历,您可以从中通过^? 获得所需的功能。
  • 我不知道有一个库可以提供你想要的东西,但你总是可以自己编写模板 Haskell。在上面的上下文中,您希望生成Traversals。这相当于制作a1 f (A x y) = A <$> f x <*> pure y; a1 f (B x y) = pure (B x y) 之类的函数,或者只获得Folda1 = folding (\t -> case t of A x _ -> Just x; _ -> Nothing) 等的只读大小写。
猜你喜欢
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
相关资源
最近更新 更多