我正在使用多值逻辑并尝试重载基本逻辑函数。
我在重载Num
和Eq
运算符时遇到了问题,但我不知道如何重载&&, ||
和not
。
有可能吗?谢谢你的回答!
答案 0 :(得分:10)
Haskell根本没有超载(= ad-hoc-polymorphism )。 +
,*
等不是函数,而是类方法:“重载”它们更像是定义OO接口/纯抽象类的具体后代而不是重载函数比方说,C ++。
逻辑运算符OTOH只是普通函数,它们在Prelude中一劳永逸地定义。
但是,在Haskell中,中缀运算符大多被视为一种特殊的函数名称,它们不属于实际的语法定义。没有什么能阻止您定义具有相同目的的新的不同的运算符,例如
class Booly b where
true :: b
false :: b
(&&?) :: b -> b -> b
(||?) :: b -> b -> b
infixr 3 &&?
infixr 2 ||?
instance Booly Bool where
true = True
false = False
(&&?) = (&&)
(||?) = (||)
instance Booly MVBool where
true = ...
事实上,如果新名称被模块限定符消除歧义就足够了:
import Prelude hiding ((&&), (||))
import qualified Prelude
class Booly b where
true :: b
false :: b
(&&) :: b -> b -> b
(||) :: b -> b -> b
infixr 3 &&
infixr 2 ||
instance Booly Bool where
true = True
false = False
(&&) = (Prelude.&&)
(||) = (Prelude.||)
答案 1 :(得分:2)
在monkeypatching意义上,Haskell中没有覆盖这样的东西。
也无法将扩展挂钩到无法扩展的内容。
您可以简单地隐藏例如&&
但这会1)不影响其他模块中&&
的语义,2)会令人困惑。
所以我会使用一些简单的东西:
-- laws should be defined for the class and instances QuickChecked/proved against these laws
class Logic a where
(&.&) :: a -> a -> a
(|.|) :: a -> a -> a
...
instance Logic Bool where
(&.&) = (&&)
(|.|) = (||)
data MultiBool = False' | True' | Perhaps | CouldBe | Possibly | Unlikely
instance Logic MultiBool where
...
答案 2 :(得分:1)
不,这是不可能的。 &&
的类型是Bool -> Bool -> Bool
,而Haskell不允许ad-hoc重载。您可以隐藏声明,但是在没有限定条件的情况下,您无法在同一模块中使用运算符同时使用布尔值和mvl值。
我建议您为mvls定义类似外观的运算符,例如&&?
。
答案 3 :(得分:1)
您无法覆盖它们,但您可以定义自己的。
infixr 3 <&&> <||>
<&&> :: ??? -> ??? -> ???
<&&> ...
答案 4 :(得分:1)
(&&)
定义为
(&&) :: Bool -> Bool -> Bool
因此,除非您不加载Prelude
或加载限定,否则不能重载该运算符。
然而,有一个类型类或多或少地执行您正在查找的内容:Data.Bits
具有以下签名:
(.&.) :: Bits a => a -> a -> a
(.|.) :: Bits a => a -> a -> a
complement :: Bits a => a -> a
Data.Bits
通常用于表示按位运算。您可以决定忽略其余的运算符(返回一些默认值)或为其分配一个有用的属性。
否则您可以定义类似的运算符。在这种情况下,一个更好的人首先定义一个类型类:
class Logic a where
land :: a -> a -> a
lor :: a -> a -> a
lnot :: a -> a
lnand :: a -> a -> a
lnand x = lnot . land x
lnor :: a -> a -> a
lnor x = lnot . lor x