[英]Haskell: “Non type-variable argument in the constraint: Eq Bit” and “No instance for (Eq Bit) arising drom a use of '=='”
data Bit = One
| Zero
deriving Show
type Bits = [Bit]
bits2String :: Bits -> String
bits2String [] = ""
bits2String (x:xs) | x == One = "1" ++ bits2String xs
| x == Zero = "0" ++ bits2String xs
This Code causes following error message:此代码导致以下错误消息:
No instance for (Eq Bit) arising drom a use of '=='
For this error you can find a lot of solutions on SO.对于这个错误,您可以在 SO 上找到很多解决方案。 They always say you need to add Eq like that:他们总是说你需要像这样添加 Eq:
bits2String :: (Eq Bit) => Bits -> String
bits2String [] = ""
bits2String (x:xs) | x == One = "1" ++ bits2String xs
| x == Zero = "0" ++ bits2String xs
But this doesnt work for me and causes following error但这对我不起作用并导致以下错误
Non type-variable argument in the constraint: Eq Bit
(Use FlexibleContexts to permit this)
{-# LANGUAGE FlexibleContexts #-} doesnt work either. {-# LANGUAGE FlexibleContexts #-} 也不起作用。
You make use of x == Zero
, so of the (==):: Eq a => a -> a -> Bool
function, but you did not make Bit
an instance of Eq
.您使用了x == Zero
,因此使用了(==):: Eq a => a -> a -> Bool
function,但您没有使Bit
成为Eq
的实例。 You can do so by adding it to the deriving
clause, such that Haskell can automatically implement an instance
of Eq
for your Bit
data type:您可以通过将其添加到deriving
子句来实现,这样 Haskell 可以为您的Bit
数据类型自动实现Eq
的instance
:
data Bit = One
| Zero
deriving (Eq, Show)
By default two items are the same if the data constructor is the same, and the parameters (but here your data constructors have no parameters, so it will only check equality of the data constructors).默认情况下,如果数据构造函数和参数相同,则两项相同(但这里您的数据构造函数没有参数,因此它只会检查数据构造函数的相等性)。
That being said, you do not need these to be an instance of Eq
, you can use pattern matching instead.话虽如此,您不需要这些是Eq
的实例,您可以使用模式匹配来代替。 Indeed:的确:
bits2String :: Bits -> String
bits2String = map f
where f Zero = '0'
f One = '1'
Here we make use of map:: (a -> b) -> [a] -> [b]
to convert a list of items to another list by applying a function to each of the items in the original list.在这里,我们使用map:: (a -> b) -> [a] -> [b]
通过将 function 应用于原始列表中的每个项目来将项目列表转换为另一个列表。 Since Bits
is a list of Bit
s, and String
is a list of Char
s, we can thus map each Bit
to a Char
to obtain a String
of '0'
s and '1'
s for the Zero
and One
s respectively.由于Bits
是Bit
的列表,而String
是Char
的列表,因此我们可以 map 将每个Bit
转换为Char
以分别获得Zero
和One
的'0'
和'1'
的String
。
The original error message is the key one:原始错误消息是关键:
No instance for (Eq Bit) arising drom a use of '=='
This arises because you are using the ==
operator, which is only available for instances of the Eq
typeclass - and you haven't given such an instance.出现这种情况是因为您使用了==
运算符,该运算符仅适用于Eq
类型类的实例 - 而您没有给出这样的实例。
That's easily fixed though.不过,这很容易解决。 For one you can easily provide the instance manually:一方面,您可以轻松地手动提供实例:
instance Eq Bit where
One == One = True
Zero == Zero = True
_ == _ = False
I wouldn't recommend that you do that though.我不建议你这样做。 You can ask Haskell to generate that exact instance for you by simply adding a deriving
clause to the type definition.您可以要求 Haskell 为您生成确切的实例,只需在类型定义中添加deriving
子句即可。 In fact you're already using one, so you can just add Eq
to the list of instances you want to derive:事实上,您已经在使用一个,因此您只需将Eq
添加到您想要派生的实例列表中:
data Bit = One
| Zero
deriving (Show, Eq)
Adding this instance is a good idea in general, because you might well need to compare Bit
s for equality at some point, especially when working with lists of them - many list functions such as elem
depend on Eq
instances for their members.通常,添加此实例是一个好主意,因为您可能需要在某些时候比较Bit
的相等性,尤其是在处理它们的列表时 - 许多列表函数(例如elem
)依赖于Eq
实例的成员。
But you can rewrite your bits2String
function to not need an Eq
instance at all, by pattern matching on the two data constructors:但是您可以通过在两个数据构造函数上进行模式匹配来重写您的bits2String
function 根本不需要Eq
实例:
bits2String :: Bits -> String
bits2String [] = ""
bits2String (One:xs) = "1" ++ bits2String xs
bits2String (Zero:xs) = "0" ++ bits2String xs
In fact, you've basically reimplemented the map
function here, so what I would likely do is to define:实际上,您基本上在这里重新实现了map
function,所以我可能会做的是定义:
bitToChar :: Bit -> Char
bitToChar Zero = '0'
bitToChar One = '1'
(especially as it's the kind of general utility function that you may well want for other things) (特别是因为它是一种通用实用程序 function,您可能希望用于其他用途)
and then接着
bits2String = map bitToChar
None of those require an Eq
instance - but it's likely a good idea to derive it anyway, for the reasons I mentioned.这些都不需要Eq
实例——但出于我提到的原因,无论如何推导出它可能是个好主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.