(我知道在SO上有一个similar question,但我认为这不是一个骗局,因为我试图实现的函数是递归的,不使用list或lambda表达式。我想知道如何以这种方式实现它,即使它们在功能上是等效的,主要是为了更好地理解Haskell。)
我正在学习如何创建检查给定布尔函数是否是重言式的函数。这是我正在阅读的书中的一个示例函数,它检查带有1个变量的布尔函数:
valid1 :: (Bool -> Bool) -> Bool
valid1 bf = (bf True) && (bf False)
以及2和3个变量:
valid2 :: (Bool -> Bool -> Bool) -> Bool
valid2 bf = (bf True True)
&& (bf True False)
&& (bf False True)
&& (bf False False)
valid3 :: (Bool -> Bool -> Bool -> Bool) -> Bool
valid3 bf = and [ bf p q r | p <- [True,False],
q <- [True,False],
r <- [True,False]]
但在我看来,除了为每个具有不同数量的变量的布尔函数创建单独的检查函数之外,应该有更好的方法。例如,我们可以做类似的事情:
validR n bf :: Int -> (Bool -> a) -> Bool
validR n bf | n == 1 = valid1 bf
| otherwise = (validR (n-1) (bf True)) && (validR (n-1) (bf False))
其中n
是bf
中变量的数量,正在检查的布尔函数。当给定具有n> 1个变量的布尔函数bf
时,该函数将分支到检查bf True
和bf False
,最终检查所有可能的真值组合。但是当我尝试加载此函数时,Haskell会给出错误消息“应用程序中的类型错误”。有没有办法调整此函数的类型声明,使其工作?
我是Haskell的新手,所以很简单的解释会非常感激。提前谢谢。
答案 0 :(得分:2)
实际上,这可以很容易地完成。
{-# LANGUAGE FlexibleInstances #-}
class BooleanFunc f where
isTautology :: f -> Bool
instance BooleanFunc Bool where
isTautology = id
instance (BooleanFunc b) => BooleanFunc (Bool -> b) where
isTautology f = isTautology (f True) && isTautology (f False)
main = do
print . isTautology $ \a b c d -> True || a || b || c || d
print . isTautology $ \a b c d -> a || b || c || d