是否可以在 Haskell 中重载逻辑运算符(&& 例如)?
Is it possible to overload logical operators (&& e.g.) in Haskell?
我正在处理多值逻辑并试图重载基本逻辑函数。
我没有重载 Num
和 Eq
运算符的问题,但我不知道如何重载 &&, ||
和 not
。
可能吗?谢谢解答!
不,这不可能。 &&
的类型是 Bool -> Bool -> Bool
,Haskell 不允许临时重载。您可以隐藏声明,但是您不能在没有限定的情况下对同一模块中的布尔值和 mvl 值使用运算符。
我建议您为 mvls 定义类似的运算符,例如 &&?
。
您不能覆盖它们,但您可以定义自己的。
infixr 3 <&&> <||>
<&&> :: ??? -> ??? -> ???
<&&> ...
(&&)
定义为
(&&) :: Bool -> Bool -> Bool
因此,除非您不加载 Prelude
,或者不加载它,否则您不能重载该运算符。
然而,有一个类型类或多或少可以满足您的需求:Data.Bits
具有如下签名:
(.&.) :: Bits a => a -> a -> a
(.|.) :: Bits a => a -> a -> a
complement :: Bits a => a -> a
Data.Bits
通常用来表示位运算。您可以决定忽略剩余的运算符(return 一些默认值)或为其分配一个有用的 属性。
否则你可以定义类似的运算符。在那种情况下,最好先定义一个类型类:
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
在 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
...
Haskell 根本没有重载 (=ad-hoc-polymorphism)。 +
、*
等不是函数而是 class 方法:“重载”它们更像是定义 OO 接口的具体后代/纯粹-abstract class 而不是在 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.||)
我正在处理多值逻辑并试图重载基本逻辑函数。
我没有重载 Num
和 Eq
运算符的问题,但我不知道如何重载 &&, ||
和 not
。
可能吗?谢谢解答!
不,这不可能。 &&
的类型是 Bool -> Bool -> Bool
,Haskell 不允许临时重载。您可以隐藏声明,但是您不能在没有限定的情况下对同一模块中的布尔值和 mvl 值使用运算符。
我建议您为 mvls 定义类似的运算符,例如 &&?
。
您不能覆盖它们,但您可以定义自己的。
infixr 3 <&&> <||>
<&&> :: ??? -> ??? -> ???
<&&> ...
(&&)
定义为
(&&) :: Bool -> Bool -> Bool
因此,除非您不加载 Prelude
,或者不加载它,否则您不能重载该运算符。
然而,有一个类型类或多或少可以满足您的需求:Data.Bits
具有如下签名:
(.&.) :: Bits a => a -> a -> a
(.|.) :: Bits a => a -> a -> a
complement :: Bits a => a -> a
Data.Bits
通常用来表示位运算。您可以决定忽略剩余的运算符(return 一些默认值)或为其分配一个有用的 属性。
否则你可以定义类似的运算符。在那种情况下,最好先定义一个类型类:
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
在 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
...
Haskell 根本没有重载 (=ad-hoc-polymorphism)。 +
、*
等不是函数而是 class 方法:“重载”它们更像是定义 OO 接口的具体后代/纯粹-abstract class 而不是在 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.||)