4

我是Haskell的新手。

我正在寻找是否有任何方法可以创建类类型的实例。

有没有办法让这段代码在不使用数据或新类型的情况下工作?

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

1 回答 1

7

你在那里写的看起来很像一个类声明,而不是一个实例。也许你是这个意思?

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

请注意,n必须是小写的,因为这是您要量化类的类型变量。如果你真的想定义一个实例,那么你,好吧,实例 nN

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

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

问题是:为什么你仍然需要自己的课程?它只会导致与标准函数的名称冲突,print并且read已经在前奏中。你实际上应该做的是用你的类型实例化那些标准类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->mN

或者,您可以只编写直接接受/产生的单态函数: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

对于整数的所有标准实例当然也一样好......

于 2016-07-30T16:27:55.827 回答