如何在haskell中创建类的类型实例?

Che*_*pop 2 haskell types church-encoding

我是Haskell的新手.

我正在寻找是否有任何方法来创建类的类型的实例.

有没有办法让这些代码在不使用数据或newtype的情况下工作?

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

instance Printable N where
        print :: N -> IO ()
        read  :: String -> N 
Run Code Online (Sandbox Code Playgroud)

当我尝试在GHCi中加载模块时,它告诉我:

Illegal polymorphic or qualified type: N
In the instance declaration for ‘Printable N’
Run Code Online (Sandbox Code Playgroud)

lef*_*out 5

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

class Printable n where
  print :: n -> IO ()
  read  :: String -> n
Run Code Online (Sandbox Code Playgroud)

请注意,n必须是小写的,因为这是您对类进行量化的类型变量.如果你真的要定义一个实例,然后你,好了,实例 nN:

instance Printable N where
  print n = ...
  read str = ...
Run Code Online (Sandbox Code Playgroud)

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

问题是:为什么你还需要自己的课程?它只会导致名称冲突的标准功能printread那些已经在序幕.你实际应该做的是用你的类型实例化那些标准类N,即

instance Show N where
  show n = ...
instance Read N where
  readsPrec _ str = ...
Run Code Online (Sandbox Code Playgroud)

也就是说,为了得到你问过的实际问题:,不可能像多态一样明确定义任何实例? n . (n->n) -> n->n.如何将编译器与更具体的类型区分开来(Int->Int) -> Int->Int,或者更常见的类型? n m . (n->m) -> n->m如何?这很无望.在正确的做事情是只把它包在NEWTYPE; 它隐藏了通用量化并允许编译器正确区分N其他类型.

或者,您可以编写直接接受/ yield的单态函数N:

showChurch :: N -> String
showChurch n = ...
readsPrecChurch :: Int -> ReadS N
readsPrecChurch _ str = ...
Run Code Online (Sandbox Code Playgroud)

实际上后者对于类型系统来说已经太多了:它ReadS N是简称

readsPrecChurch :: Int -> String -> [(? n . (n->n) -> n->n, String)]
Run Code Online (Sandbox Code Playgroud)

列表中的通用量化?哦,哦.这是一种不可预测的类型.GHC确实有一个-XImpredicativeTypes扩展,但它并没有真正起作用.

再次,通过不公开使用多态类型来避免这些问题.Rank-N类型(特别是镜头)有一些很好的用途,但大多数时候它们完全是过度杀伤和不必要的.实际上,使用像这样的教堂数字肯定没有充分的理由.

newtype N = Church { getChurch :: ? n . (n->n) -> n->n }
Run Code Online (Sandbox Code Playgroud)

将允许您毫无问题地定义任意实例或函数.而且,实际上,只是做

type N = Int
Run Code Online (Sandbox Code Playgroud)

对于整数来说,所有标准实例当然同样好......

  • 对不起,我的问题解释得不好,但您仍然回答正确,非常感谢! (2认同)