我可以使用 DerivingVia 派生与元组同构的数据类型的实例吗
Can I use DerivingVia to derive instances for data types isomorphic to tuples
给定以下数据类型
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 和答案,但我希望有一个需要更少样板的解决方案。
受到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)
DerivingVia paper 有一个部分是关于使用 Generic
为“通过 Generic
同构”的事物派生任意 类 的。参见 4.3.
感觉好像在hackage上看到过适配库的方法,但是现在好像找不到了。
但是,我不确定它是否适合您的情况,因为 (a, b)
和您的类型可能不具有相同的 Generic
表示(您的类型有记录字段)。
“数据类型通用手术”在这种情况下也可能有用 - https://github.com/Lysxia/generic-data-surgery#readme
给定以下数据类型
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 和答案,但我希望有一个需要更少样板的解决方案。
受到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)
DerivingVia paper 有一个部分是关于使用 Generic
为“通过 Generic
同构”的事物派生任意 类 的。参见 4.3.
感觉好像在hackage上看到过适配库的方法,但是现在好像找不到了。
但是,我不确定它是否适合您的情况,因为 (a, b)
和您的类型可能不具有相同的 Generic
表示(您的类型有记录字段)。
“数据类型通用手术”在这种情况下也可能有用 - https://github.com/Lysxia/generic-data-surgery#readme