什么,你已经写了有看上去很像一个类声明,不是一个实例。也许你的意思是?
class Printable n where
print :: n -> IO()
read :: String -> n
注意,n
必须是小写的,因为这是类型变量你在quantising类。如果你真的要定义一个实例,然后你,好了,实例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 = ...
也就是说,去你问的实际问题:没有,这是不可能的定义任何实例明智地用于多态类型如∀ 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
与所有前来整数当然是一样好,标准情况下...
为什么你不希望使用'newtype'? – ErikR
如果我使用新类型或数据,我需要写下如下内容:'newtype N = N(n - > n) - > n - > n)',然后重写'(+)(N a)(N b) = stuff'而不是'(+)= \ ab - > stuff'而不拆开a或b。 – CheeseLollipop
在当前GHC中最好避免盲目性。没有办法,但使用'newtype'或'data'。 (也可以查看安全强制,这使得'newtype'在某些情况下更容易处理)。 – chi