更广泛的新型派生
当在特定的类上下文中使用时,Newtypes通常用于改变某些类型的行为。 例如,可以使用Data.Monoid.All
包装来改变Bool
在用作Monoid
时的行为。
我目前正在撰写这样一种适用于大量不同类型的新型包装。 包装应该改变一个特定类实例的行为。 它可能看起来像这样:
newtype Wrapper a = Wrapper a
instance Special a => Special (Wrapper a) where
-- ...
但是,添加这个包装器通常会改变包装类型的可用性。 例如,如果我以前能够使用函数mconcat :: Monoid a => [a] -> a
,我现在无法将它用于包装值的列表。
我当然可以使用-XGeneralizedNewtypeDeriving
和-XGeneralizedNewtypeDeriving
newtype Wrapper a = Wrapper a deriving (Monoid)
-XGeneralizedNewtypeDeriving
newtype Wrapper a = Wrapper a deriving (Monoid)
。 但是,这只能解决Monoid
和其他类的问题,而我将处理一个充满不同类的开放世界,而孤立的孤立泛型新类型派生并不是真正的实际选择。 理想情况下,我想写deriving hiding (Special)
(派生每个类除Special
之外),但这不是有效的Haskell,当然。
有没有这样做或我只是拧了,需要添加一个GHC功能请求?
看, GeneralizedNewtypeDeriving
的新型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
你可以随时使用它,只要你需要typeclass实例
intWrapperNum :: Dict (Num (Wrapper Int))
intWrapperNum = addDictWrapper Dict
two :: Wrapper Int
two = case intWrapperNum of
Dict -> 1 + 1
这个传递显式字典的系统非常普遍,并且有一个非常好的(尽管是实验性的)库来支持它,称为Data.Constraint
恐怕GHC中没有直接的方法。 但我认为你可以使用Template Haskell解决你的问题。
链接地址: http://www.djcxy.com/p/7533.html上一篇: Even more generalized newtype deriving
下一篇: Is there a way to define an existentially quantified newtype in GHC Haskell?