如何写一个可派的类?

Vek*_*weg 13 haskell

我有这个

data Something = Something Integer deriving (MyClass, Show)

class MyClass a where   
    hello :: MyClass a => a -> a

instance MyClass Integer where
    hello i = i + 1

main = print . hello $ Something 3
Run Code Online (Sandbox Code Playgroud)

但MyClass不可导出.为什么?

sab*_*uma 13

GHC无法神奇地派生任意数据类型的实例.但是,它可以利用newtype声明为相同的基础类型创建新名称以便为使用该GeneralizedNewtypeDeriving扩展的用户派生实例 的事实.所以,你可以这样做:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype Something = Something Integer deriving (MyClass, Show)

class MyClass a where
    hello :: MyClass a => a -> a

instance MyClass Integer where
    hello i = i + 1

main = print . hello $ Something 3
Run Code Online (Sandbox Code Playgroud)

GHC无法派生新实例的原因是它不知道实例应该是什么.即使您的数据类型只有一个字段,它也可能不一定与该字段相同.为newtypes 派生实例的能力很方便,因为它们通常用于为某些类型类提供不同的行为,或者作为一种使用类型系统来分隔代码中具有相同类型但用途不同的事物的方法.

  • @DanBurton 1.它与类型相等没有正确交互,请参阅我的博客http://joyoftypes.blogspot.com/2012/08/generalizednewtypederiving-is.html并让你输入`unsafeCoerce` 2.它打破依赖的模块"单实例属性"(我认为我们应该放弃,但是除此之外)只有Haskell 98因为你可以定义`class IntIso a where intIso :: f Int - > fa` with instance`Int`和`newtype X = X Int推导IntIso`它允许你在`Set Int`和`Set X`之间强制但是`X`可能有不同的排序关系,因此可以破坏Data.Set. (4认同)
  • `newtype`派生很方便,但目前的实施并不安全.我说只在早期版本的代码中使用.新的`default`/generic框架更通用,更安全(但也更笨重),所以尽可能使用它. (2认同)
  • "NewtypeDeriving"的所有邪恶例子都涉及到有人开始做恶.如果你理智地使用它,它将不是一个问题.而且无论如何它都会在新的GHC中得到修复. (2认同)
  • 顺便说一句,它已经*已修复。不幸的是,该修复程序最终拒绝了很多完美的代码,但至少可以避免类型安全问题。 (2认同)

asm*_*asm 13

您可能希望查看有关通用编程GHC文档.
您需要创建一个可以处理任意类型的泛型表示的类.我不认为您给出的具体示例对于可派生类是合理的.

  • +1很高兴有人提出这个问题作为回答.你是否想成为一个合理的例子呢? (2认同)