【发布时间】:2017-09-21 22:40:09
【问题描述】:
假设定义了以下newtype:
newtype A a = A a
还有一个功能:
f :: A a -> A a
现在假设我定义了另一个newtype,其中包含A a:
newtype B a = B (A a)
然后我想定义一个函数fb,它在B a 上运行,但只使用f:
fb :: B a -> B a
fb (B x) = B (f x)
现在这很不方便,因为我必须解包并将值包装在B a 类型的元素中。如果我只需要定义一个这样的fb,这不会那么糟糕,但如果它们有很多,这将变得相当乏味。
如果有一个带函数的类型类就好了:
(<$$>) :: k a -> k b -> h (k a) -> h (k b)
这样fb就可以改写为:
fb = (f <$$>)
也许这样的抽象已经存在,但我找不到。
【问题讨论】:
-
对于新类型的特殊情况,你应该只使用
Data.Coerce,它给你coerce :: (a -> a) -> A a -> A a和coerce :: (A a -> A a) -> B a -> B a和coerce (a -> a) -> B a -> B a。 -
我认为safe coercions 是自动包装/展开的方式。
-
@user2407038 确实如此,但不一定必须在使用站点。对于新类型,
instance Functor N where fmap = coerce是相当合理的。 -
我看不出你提出的类型类会有什么帮助。
B a -> B a类型与h (k a) -> h (k b)不统一。 -
<$$>让人想起 newtype / newtype-generics 包中的over。但是over需要外部 newtype 构造函数作为附加参数。 hackage.haskell.org/package/newtype-generics-0.5.1/docs/…