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)
你在那里写的东西看起来很像一个类声明,而不是一个实例.也许你的意思是这个?
class Printable n where
print :: n -> IO ()
read :: String -> n
Run Code Online (Sandbox Code Playgroud)
请注意,n
必须是小写的,因为这是您对类进行量化的类型变量.如果你真的要定义一个实例,然后你,好了,实例 n
有N
:
instance Printable N where
print n = ...
read str = ...
Run Code Online (Sandbox Code Playgroud)
此时,类型签名都是固定的(来自类定义),您需要编写的是这些函数的实际绑定,因此它必须是=
,而不是::
.
问题是:为什么你还需要自己的课程?它只会导致名称冲突的标准功能print
和read
那些已经在序幕.你实际应该做的是用你的类型实例化那些标准类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)
对于整数来说,所有标准实例当然同样好......