首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从记录中的字段派生实例

从记录中的字段派生实例
EN

Stack Overflow用户
提问于 2019-05-03 07:17:29
回答 1查看 187关注 0票数 5

示例代码:

代码语言:javascript
复制
{-# LANGUAGE NamedFieldPuns #-}

module Sample where

class Sample a where
  isA :: a -> Bool
  isB :: a -> Bool
  isC :: a -> Bool

data X =
  X

instance Sample X where
  isA = undefined
  isB = undefined
  isC = undefined

data Wrapper = Wrapper
  { x :: X
  , i :: Int
  }

instance Sample Wrapper where
  isA Wrapper {x} = isA x
  isB Wrapper {x} = isB x
  isC Wrapper {x} = isC x

在这里,我有一些由X实现的类,然后是另一个包含X的记录Wrapper

我希望Wrapper通过其字段x派生Sample实例。

我知道我可以通过获取字段并为每个函数自己调用它来做到这一点,如所示。

是否有某种标志或方法来自动地或仅一次地这样做?

这似乎与DerivingViaGeneralisedNewtypeDeriving相似,但两者似乎都只针对newtype或强制类型。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-03 11:08:55

以下是一些不需要任何扩展的策略,但是为了方便地派生这些类,需要预先花费一些费用。

请注意,由于Sample不是一个新类型,因此不能保证它只包含一个X,而不包含两个、更多或可变的数量(Maybe XEither X X?)。因此,正如您将看到的那样,您的选项必须在结构中显式地选择X,这可能是自动导出该扩展为不存在的原因之一。

导出一个函数而不是多个函数

为了满足Sample,我们确实需要一个X。让我们把它变成一个典型的:

代码语言:javascript
复制
class HasX t where
  getX :: t -> X

class Sample t where
  isA :: t -> Bool
  isB :: t -> Bool
  isC :: t -> Bool
  default isA :: HasX t => t -> Bool
  isA = isA . getX
  default isB :: HasX t => t -> Bool
  isB = isB . getX
  default isC :: HasX t => t -> Bool
  isC = isC . getX

instance HasX Wrapper where
  getX = x

instance Sample Wrapper -- no implementation necessary

通过泛型派生

假设我们只想处理将X作为第一个字段的记录。为了匹配类型结构,我们可以使用GHC.Generics。在这里,我们向第一个字段添加了一种使HasX默认的方法:

代码语言:javascript
复制
class HasX t where
  getX :: t -> X
  default getX :: (Generic a, HasX (Rep a)) => t -> X
  getX = getX . from

instance HasX (M1 D d (M1 C c (M1 S s (Rec0 X) :*: ff))) o where
  getX (M1 (M1 ((M1 (K1 x)) :*: _))) = x

HasX的最后一个实例将任何记录(M1 D)与一个构造函数(M1 C)匹配,该构造函数具有多个(:*:)字段(M1 S),第一个字段为类型(Rec0) X

(是的,泛型实例很难处理。编辑欢迎)

(要查看Wrapper的泛型类型的确切表示形式,请检查GHCi控制台中的Rep Wrapper。)

现在,可以将Wrapper的实例编写为:

代码语言:javascript
复制
data Wrapper = Wrapper
  { x :: X
  , i :: Int
  }
  deriving (Generic, HasX, Sample)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55964963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档