【问题标题】:Can I use DerivingVia to derive instances for data types isomorphic to tuples我可以使用 DerivingVia 为与元组同构的数据类型派生实例吗
【发布时间】:2022-02-21 19:48:16
【问题描述】:

给定以下数据类型

data Both a b = Both { left :: a, right :: b }

我可以像这样为 Applicative 等编写实例(此处省略 Functor,因为我们可以使用 DeriveFunctor):

instance Monoid a => Applicative (Both a) where
    pure x = Both mempty x
    Both u f <*> Both v x = Both (u <> v) (f x)

由于Both(a,b) 同构,我想知道是否可以使用DerivingVia 来派生实例:

data Both a b = ... deriving Applicative via ((,) a)

这会导致如下错误消息:

    • Couldn't match representation of type ‘(a, a1)’
                               with that of ‘Both a a1’
        arising from the coercion of the method ‘pure’
          from type ‘forall a1. a1 -> (a, a1)’
            to type ‘forall a1. a1 -> Both a a1’
    • When deriving the instance for (Applicative (Both a))

我将其解释为“编译器不知道如何将 Both 转换为 (,)”。我如何告诉编译器使用显而易见的方式来做到这一点?

我已经看过 this question 和答案,但我希望找到一个需要更少样板的解决方案。

【问题讨论】:

    标签: haskell deriving derivingvia


    【解决方案1】:

    受到this answer 的启发,并借助generic-data 包可以编写:

    {-# LANGUAGE DeriveGeneric, DerivingStrategies, DerivingVia #-}
    
    import GHC.Generics
    import Generic.Data
    
    data Both a b = Both {left :: a, right :: b}
      deriving stock (Generic1)
      deriving (Functor, Applicative) via Generically1 (Both a)
    

    【讨论】:

      【解决方案2】:

      DerivingVia paper 有一节介绍使用Generic 为“通过Generic 同构”的事物派生任意类。见 4.3。

      我觉得我已经看到了适用于 hackage 库的方法,但我现在似乎找不到它。

      但是,我不确定它是否适用于您的情况,因为 (a, b) 和您的类型可能没有相同的 Generic 表示(您的类型有记录字段)。 “数据类型通用手术”在这种情况下也可能有用 - https://github.com/Lysxia/generic-data-surgery#readme

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-18
        • 1970-01-01
        • 2018-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多