给定以下数据类型
data Both a b = Both { left :: a, right :: b }我可以像这样为应用程序等编写实例(在这里省略函子,因为我们可以使用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转换为(,)”。我如何告诉编译器使用显而易见的方法来完成这一任务?
我已经看到了这个问题和答案,但我希望有一个解决方案,需要更少的样板。
发布于 2022-02-21 11:18:48
受这个答案的启发,在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)发布于 2022-02-21 11:48:16
DerivingVia纸有一节介绍如何使用Generic为“通过Generic同构”的事物派生任意类。见4.3。
我觉得我已经看到了适应于一个黑客库的方法,但我现在似乎找不到它。
但是,我不确定它是否适用于您的情况,因为(a, b)和您的类型可能没有相同的Generic表示(您的类型有记录字段)。“数据类型通用手术”在这种情况下也是有用的-- https://github.com/Lysxia/generic-data-surgery#readme。
https://stackoverflow.com/questions/71205425
复制相似问题