-->

更广义NEWTYPE推导(Even more generalized newtype derivin

2019-08-01 01:11发布

Newtypes通常用于在某一类的上下文中使用时,更改某些类型的行为。 例如,一种将使用Data.Monoid.All包装改变的行为Bool作为使用时Monoid

我目前正在写这样一个适用于大范围的不同类型的NEWTYPE包装。 该包装应该是改变一个特定的类实例的行为。 这可能是这样的:

newtype Wrapper a = Wrapper a

instance Special a => Special (Wrapper a) where
  -- ...

然而,加入这个包装往往会改变包装类型的可用性。 例如,如果我以前能使用的功能mconcat :: Monoid a => [a] -> a ,我不能现在用它来包裹值的列表。

当然,我可以使用-XGeneralizedNewtypeDerivingnewtype Wrapper a = Wrapper a deriving (Monoid) 。 然而,这仅仅解决了这个问题Monoid并没有其他类,而我会用一个开放的世界充满了不同类别的被处理,和独立孤儿广义NEWTYPE推导是不是一个真正的实际的选择。 理想情况下,我想写出deriving hiding (Special) (除派生每个类Special ),但是这不是有效的Haskell,当然。

是否有这样做的一些方法或者我只是拧紧,并需要添加一个GHC功能提出要求?

Answer 1:

你看, GeneralizedNewtypeDeriving是不安全的 。 本着这种精神,在这里是做什么的都是不安全的

{-# LANGUAGE GADTs, ConstraintKinds #-}
import Data.Monoid
import Unsafe.Coerce

data Dict c where
  Dict :: c => Dict c

newtype Wrapper a = Wrapper a

addDictWrapper :: Dict (f a) -> Dict (f (Wrapper a))
addDictWrapper = unsafeCoerce

那么你就可以随时随地使用它,你需要的类型类实例

intWrapperNum :: Dict (Num (Wrapper Int))
intWrapperNum = addDictWrapper Dict

two :: Wrapper Int
two = case intWrapperNum of
           Dict -> 1 + 1

该系统通过各地明确的字典是非常普遍,并具有相当不错的(虽然实验)库来支持它所谓Data.Constraint



Answer 2:

恐怕是没有直接的方法怎么做,在GHC。 但我认为,你可以使用解决您的问题模板哈斯克尔 。



文章来源: Even more generalized newtype deriving