【发布时间】:2020-09-19 12:33:13
【问题描述】:
每个人。我是 Haskell 的新手。我想定义一个适用于任何数字的类型类实例。举个例子,我写一个简单的typeclass:
class YesNo a where
yesno :: a -> Bool
基本上,yesno 函数模仿 JavaScript 的布尔检查行为。如果你给它一个“真实”的值,它会返回True,否则它会返回False。以下是一些使用它的示例:
yesno "3" -- True
yesno 3.0 -- True
yesno 0 -- False
yesno "" -- False
yesno [] -- False
有一个问题,在 Haskell 中有几种类型来表示不同的数字:Int、Integer、Float... 虽然我可以为这些类型编写一个 yesno 函数,但我有分别为它们定义实例。
class YesNo a where
yesno :: a -> Bool
instance YesNo Integer where
yesno 0 = False
yesno _ = True
instance YesNo Int where
yesno 0 = False
yesno _ = True
instance YesNo Float where
yesno 0 = False
yesno _ = True
instance YesNo Double where
yesno 0 = False
yesno _ = True
虽然有效,但写起来看起来非常麻烦和无聊。我想知道是否有更简洁的方法来完成这个,比如:
instance YesNo Integer where
instance YesNo Int where
instance YesNo Float where
instance YesNo Double where
yesno 0 = False
yesno _ = True
代码显然不符合 Haskell 的语法。我还尝试为实例添加类型约束。
instance (Num a) => YesNo a where
yesno 0 = False
yesno _ = True
我希望它会起作用,但它没有,并且在 GHCi 中显示了以下错误。看来实例的类型必须是具体的,类型类是不可接受的。
TypeClass.hs:39:21: error:
• Illegal instance declaration for ‘YesNo a’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
• In the instance declaration for ‘YesNo a’
【问题讨论】:
-
您是否尝试过编译器的建议并启用
FlexibleInstances?您可以通过将{-# LANGUAGE FlexibleInstances #-}放在文件顶部来做到这一点。 -
通常同意@RobinZigmond 的观点,即
-XFlexibleInstances完全没有问题,但是在这种情况下,它只是把石头踢到了路上:首先你还需要-XUndecidableInstances(仍然可以),然后一旦你有instance (Num a) => YesNo a工作所有 other 实例,如instance YesNo Bool将会中断,因为它们是 overlapping 就语言所知。同样,GHC 确实具有允许重叠实例的功能,但我不建议这样做。
标签: haskell