我正在尝试使用DerivingVia
具有功能依赖关系的多参数类型类的实例定义来削减样板文件。
我有这些类型和类:
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DerivingVia #-}
newtype Wrapper t = Wrapper t
newtype Wrapper2 t = Wrapper2 t
class MyEq a f | a -> f where
eq :: a -> a -> f Bool
-- Instance for 'Wrapper2'
instance Eq t => MyEq (Wrapper2 t) Wrapper2 where
eq (Wrapper2 t) (Wrapper2 t') = Wrapper2 (t == t')
我想MyEq (Wrapper Int) Wrapper
使用deriving via
.
我的第一次尝试是使用:
deriving via Wrapper2 instance MyEq (Wrapper Int) Wrapper
正如论文第 6.2 节所讨论的那样,https://www.kosmikus.org/DerivingVia/deriving-via-paper.pdf,这寻找一个MyEq (Wrapper Int) Wrapper2
实例,第二个参数已“更改”但第一个参数仍然是Wrapper Int
.
显然instance MyEq (Wrapper Int) Wrapper2
不存在,因为我实现了instance MyEq (Wrapper2 Int) Wrapper2
.
我不能通过创建来“作弊”(参见Wrapper
第一个类型参数):
-- Instance for 'Wrapper2'
instance Eq t => MyEq (Wrapper t) Wrapper2 where
eq (Wrapper2 t) (Wrapper2 t') = Wrapper2 (t == t')
因为在这种情况下,Wrapper t -> Wrapper2
不尊重功能依赖性。
我可以通过重写和删除函数依赖来轻松解决这个问题eq :: f a -> f a -> f Bool
,但我想避免更改这个 API。