我是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’
答案 0 :(得分:5)
你在那里写的内容看起来很像类声明,而不是实例。也许你的意思是这个?
class Printable n where
print :: n -> IO ()
read :: String -> n
请注意,n
必须是小写的,因为这是类型变量,您正在量化该类。如果你真的想要定义一个实例,那么你,{em>实例化 n
与N
:
instance Printable N where
print n = ...
read str = ...
此时类型签名都是固定的(来自类定义),您需要编写的是这些函数的实际绑定,因此它必须是=
,而不是::
。
问题是:为什么你还需要自己的班级?它只会导致与前奏中已有的标准函数print
和read
发生名称冲突。你实际应该做的是使用你的N
类型实例化那些标准类,即
instance Show N where
show n = ...
instance Read N where
readsPrec _ str = ...
那就是说,为了得到你问的实际问题: no ,不可能为像{{1}这样的多态类型明智地定义任何实例}}。如何将编译器与更具体的类型(如∀ n . (n->n) -> n->n
)或更常见的类型(如(Int->Int) -> Int->Int
)区分开来?这很无望。 正确的要做的就是将其包装成newtype;它隐藏了通用量化,并允许编译器正确区分∀ n m . (n->m) -> n->m
与其他类型。
或者,您可以直接编写接受/生成N
的单态函数:
N
实际上后者对于类型系统已经太多了:showChurch :: N -> String
showChurch n = ...
readsPrecChurch :: Int -> ReadS N
readsPrecChurch _ str = ...
是
ReadS N
列表中的通用量化?哦,哦。这是一种不可预测的类型。 GHC确实有readsPrecChurch :: Int -> String -> [(∀ n . (n->n) -> n->n, String)]
扩展名,但它确实没有用。
同样,通过不公开使用多态类型来避免这些问题。 Rank-N类型(特别是镜头)有一些很好的用途,但大多数时候它们完全是过度杀伤和不必要的。实际上,使用像这样的教堂数字肯定没有充分的理由。
-XImpredicativeTypes
将允许您毫无问题地定义任意实例或函数。而且,实际上,只是做
newtype N = Church { getChurch :: ∀ n . (n->n) -> n->n }
对于整数来说,所有标准实例当然都一样好......