gpt4 book ai didi

haskell - 使用仿函数派生类函数的广义新类型

转载 作者:行者123 更新时间:2023-12-02 11:31:55 26 4
gpt4 key购买 nike

我正在开发一个表示键/值映射的类,并且我有一个基本上类似于 alterF 的函数:

class C t where
...
alterF :: Functor f =>
(Maybe (Value t) -> f (Maybe (Value t))) -> Key t -> t -> f t

不幸的是,这打破了 GeneralisedNewtypeDeriving 。在某些情况下,这是合理的,因为根据我的理解,GeneralizedNewtypeDeriving 本质上使用 Coercible和函数 coerceCoercible 表示在表示上相等的类型,即它们在运行时具有相同的表示,因此我们可以在它们之间免费进行转换。例如,给定:

newtype T a = T a

我们有:

Coercible a (T a)
Coercible (T a) a

但我们(一般来说)没有:

Coercible (f a) (f (T a))
Coercible (f (T a)) (f a)

例如,GADT 违反了这种表示平等。但 f 有很多值确实有效。例如:

Coercible (Maybe a) (Maybe (T a))
Coercible (Maybe (T a)) (Maybe a)
Coercible [a] [T a]
Coercible [T a] [a]
Coercible (Identity a) (Identity (T a))
Coercible (Identity (T a)) (Identity a)

我还想到这个实例可以写成:

Functor f => Coercible (f a) (f (T a))
Functor f => Coercible (f (T a)) (f a)

只需使用fmap。与通常的强制不同,这在运行时不是免费的,但它会起作用。

所以我有一个包含 10 个函数的类,其中 9 个可以与 GeneralizedNewtypeDeriving 配合使用。最后一个没有,可以使用 fmap 机械地解决。我是否必须为所有类函数编写自定义包装/展开实现,或者有没有办法要求我只为问题函数编写实现,或者哄骗 GHC 使用 fmap 作为一部分它的GeneralizedNewtypeDeriving

最佳答案

如果f是一个Functor,你可以为它制作一个“代表性包装器”

data Rep f a where
Rep :: (b -> a) -> f b -> Rep f a

它与f同构,只是它在a中具有代表性,本质上是对f可能具有的任何标称方差的存在量化。我认为这个结构恰好有一些奇特的范畴论名称,但我不记得它是什么。要从 Rep f a 中恢复 f a,您需要使用 fFunctorhood。

您可以在您的方法中使用此包装器,确保您的类具有不同的代表性。

alterFRep :: (Functor f) 
=> (Maybe (Value t) -> Rep f (Maybe (Value t))) -> Key t -> t -> Rep f t

然后通过使用与Rep f的同构,使真正的“方法”只是一个常规函数。您还可以为实例作者创建一个方便的方法:

toAlterFRep :: 
(forall f t. (Functor f) => (Maybe (Value t) -> f (Maybe (Value t))) -> Key t -> t -> f t)
-> (forall f t. (Functor f) => (Maybe (Value t) -> Rep f (Maybe (Value t))) -> Key t -> t -> Rep f t)

所以他们不必担心 Rep 到底是什么,他们只需正常实现 alterF 并对其使用 toAlterFRep 即可。

关于haskell - 使用仿函数派生类函数的广义新类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48848571/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com