Haskell:创建约束并应用于数据类型



我正在尝试创建类约束并应用于新的数据类型,但我无法让这段代码进行类型检查。 有人可以帮忙吗? 我哪里做错了?

{-# 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 中,数字文字(如1542)没有具体类型。它们有类型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是什么。

最新更新