2016-07-30 97 views
1

我是哈斯克尔的新手。如何在haskell中创建类的类型实例?

我在寻找是否有任何方法来创建一个类的类型的实例。

有没有什么办法让这段代码工作而不使用数据或newtype?

type N = ∀n. (n -> n) -> n -> n 

instance Printable N where 
     print :: N -> IO() 
     read :: String -> N 

当我尝试加载GHCI模块它告诉我:

Illegal polymorphic or qualified type: N 
In the instance declaration for ‘Printable N’ 
+4

为什么你不希望使用'newtype'? – ErikR

+0

如果我使用新类型或数据,我需要写下如下内容:'newtype N = N(n - > n) - > n - > n)',然后重写'(+)(N a)(N b) = stuff'而不是'(+)= \ ab - > stuff'而不拆开a或b。 – CheeseLollipop

+0

在当前GHC中最好避免盲目性。没有办法,但使用'newtype'或'data'。 (也可以查看安全强制,这使得'newtype'在某些情况下更容易处理)。 – chi

回答

5

什么,你已经写了有看上去很像一个类声明,不是一个实例。也许你的意思是?

class Printable n where 
    print :: n -> IO() 
    read :: String -> n 

注意,n必须是小写的,因为这是类型变量你在quantising类。如果你真的要定义一个实例,然后你,好了,实例nN

instance Printable N where 
    print n = ... 
    read str = ... 

此时类型签名都是固定的(从类定义),你需要什么写是这些函数的实际绑定,因此它必须是=,而不是::

问题是:为什么你需要自己的班?这只会导致名称与标准功能printread的冲突已经在前奏中。你真正应该做的是实例这些标准类N类型,即

instance Show N where 
    show n = ... 
instance Read N where 
    readsPrec _ str = ... 

也就是说,去你问的实际问题:没有,这是不可能的定义任何实例明智地用于多态类型如∀ n . (n->n) -> n->n。编译器应该如何将它与(Int->Int) -> Int->Int等更具体的类型或∀ n m . (n->m) -> n->m等更通用的类型区分开来?这是相当无望的。 正确要做的事情就是把它包装成一种新类型;隐藏了通用量化并允许编译器将N与其他类型区分开来。

或者,你可以只写单型功能接受/产量N直接:

showChurch :: N -> String 
showChurch n = ... 
readsPrecChurch :: Int -> ReadS N 
readsPrecChurch _ str = ... 

其实后者已经太多类型系统:ReadS N是短期的

readsPrecChurch :: Int -> String -> [(∀ n . (n->n) -> n->n, String)] 

列表中的通用量化?呃哦。这是一种不确定的类型。 GHC确实有一个-XImpredicativeTypes扩展名,但它并没有真正的工作。

同样,只是通过不公开使用多态类型来避免这些问题。Rank-N类型(特别是镜头)有一些很好的用途,但是大多数时候它们完全没有必要。实际上使用这样的教堂数字当然没有什么好的理由。

newtype N = Church { getChurch :: ∀ n . (n->n) -> n->n } 

将允许您定义任意实例或函数没有问题。而且从实践上来说,简单地做

type N = Int 

与所有前来整数当然是一样好,标准情况下...

+0

对不起,我解释了我的问题,但你仍然正确回答,非常感谢! – CheeseLollipop

相关问题