我正在尝试创建类约束并应用于新的数据类型,但我无法让这段代码进行类型检查。 有人可以帮忙吗? 我哪里做错了?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
class NewConstraint a where
getTrue :: a -> Bool
newtype Identity a = Identity a
deriving (Eq, Show, Num)
instance (Num a, NewConstraint a) =>
NewConstraint (Identity a) where
getTrue x = True
test :: Bool
test = getTrue (Identity 1)
这里有两个问题:缺少实例约束和多态数字文字。
首先:缺少实例约束。
当你编写这样的代码时:
instance NewConstraint a => NewConstraint (Identity a) where
它的意思是">每种形状Identity a
,对于每一个可能的a
,都有一个NewConstraint
的实例;但所讨论的a
也必须有一个NewConstraint
的实例。
所以当你写getTrue (Identity 1)
时,编译器会寻找NewConstraint
的实例,并为Identity a
找到一个实例。但a
是什么?好吧,这是一个整数,所以假设它是Int
.
但是您的实例声明说a
必须有一个NewConstraint
的实例。因此,编译器现在查找NewConstraint Int
的实例。并且没有找到它。所以它给你一个错误。
要解决此问题,请添加一个实例NewConstraint Int
,如下所示:
instance NewConstraint Int where getTrue _ = True
或者从Identity a
实例中删除NewConstraint
约束,如下所示:
instance Num a => NewConstraint (Identity a) where
秒:多态数字文字。
在 Haskell 中,数字文字(如1
、5
或42
)没有具体类型。它们有类型Num a => a
,意思是">任何类型a
,只要它有一个Num
的实例">
那么当你写1
时,它是什么类型呢?可能是Int
(就像我上面建议的那样),可以是Double
的,可能是Complex
的。编译器无法知道您的意思。
通常,还有其他一些来源可以推断类型。也许数字文字作为参数传递给某个函数,并且该函数需要Int
。好吧,那么编译器可以说你的意思是Int
.
但是在您的情况下,没有这样的来源。所以编译器不知道。
因此,为了帮助编译器,您必须指定类型,如下所示:
test = getTrue (Identity (1 :: Int))
最后请注意,如果从实例NewConstraint (Identity a)
中删除NewConstraint a
约束,则不必指定1 :: Int
的类型。
是的,编译器仍然不知道1
的类型,但它不会在乎。它不需要找到NewConstraint a
的实例,所以不需要知道a
是什么。