haskell - 更广义的新类型推导

标签 haskell ghc typeclass newtype

在某些类上下文中使用时,新类型通常用于更改某些类型的行为。例如,可以使用 Data.Monoid.All用于更改 Bool 行为的包装器当用作 Monoid .

我目前正在编写一个适用于各种不同类型的新型包装器。包装器应该改变一个特定类实例的行为。它可能看起来像这样:

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 的问题。并且没有其他类,而我将处理一个充满不同类的开放世界,并且独立的孤儿广义新类型派生并不是一个实际的选择。理想情况下,我想写 deriving hiding (Special) (派生除 Special 之外的每个类),但这当然不是有效的 Haskell。

有什么方法可以做到这一点,还是我只是搞砸了,需要添加 GHC 功能请求?

最佳答案

看, GeneralizedNewtypeDeriving is unsafe .在这种情况下,这是一种不安全的做法

{-# 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

关于haskell - 更广义的新类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12665779/

相关文章:

Haskell 断言一种类型将与另一种类型匹配

haskell - 从参数的约束推断类型族的约束

scala - Scala 能否约束对象图,以便只有与上下文相关的对象可见?

haskell - Control.Monad.State API 最近是否发生了变化?

haskell - 从类型列表中获取常规列表

haskell - 你将如何在 Haskell 中(重新)实现迭代?

haskell - Haskell 中的 Control.Parallel 编译问题

haskell - 修复 ghc-pkg 检查指出的问题

scala - 在 Shapeless 中,我可以为非 case 类提供 `LabelledGeneric` 的实例,以启用类型类实例的自动派生吗?

haskell - Coyoneda 没有更高等级的类型,但实际上它是什么类型?