Haskell中匿名函数的真值表

1nt*_*nce 7 logic haskell boolean truthtable

我正在尝试为给定的布尔表达式生成真值表.我可以通过创建一个新的数据类型BoolExpr来做到这一点,但我想用匿名函数来做.它应该像这样工作:

> tTable (\x y -> not (x || y))
output:
F F | T
F T | F
T F | F
T T | F
Run Code Online (Sandbox Code Playgroud)

我的方法:

tbl p = [(uncurry p) tuple | tuple <- allval]
        where allval=[(x,y) | x <- [False,True], y <- [False,True]]
Run Code Online (Sandbox Code Playgroud)

这有效,但仅适用于2个参数.我想为任意数量的参数做这件事.所以我想我会创建一个从List获取Arguments的函数:

argsFromList f []     = f
argsFromList f (x:xs) = argsFromList (f x) xs
Run Code Online (Sandbox Code Playgroud)

这不起作用:

 Occurs check: cannot construct the infinite type: t = t1 -> t
   Expected type: t -> [t1] -> t1 -> t
   Inferred type: (t1 -> t) -> [t1] -> t1 -> t
 In the expression: argsFromList (f x) xs
Run Code Online (Sandbox Code Playgroud)

我不明白这里的问题是什么.如果有人能指出我正确的方向或发布一个链接,我将非常感激.

Sjo*_*her 13

如果要为具有任意数量参数的布尔函数构建真值表,则需要创建一个必须适用于多种类型的函数,因此您必须使用类型类:

{-# LANGUAGE FlexibleInstances #-}

class TruthTable a where
  truthTable :: a -> [([Bool], Bool)]

instance TruthTable Bool where
  truthTable b = [([], b)]

instance TruthTable a => TruthTable (Bool -> a) where
  truthTable f = [ (True  : inps, out) | (inps, out) <- truthTable (f True)] ++ 
                 [ (False : inps, out) | (inps, out) <- truthTable (f False)]
Run Code Online (Sandbox Code Playgroud)

例如:

*Main> mapM_ print $ truthTable (&&)
([True,True],True)
([True,False],False)
([False,True],False)
([False,False],False)
Run Code Online (Sandbox Code Playgroud)


C. *_*ann 4

这里的问题是您尝试使用不同类型的递归步骤递归调用函数。考虑定义:

argsFromList f []     = f
argsFromList f (x:xs) = argsFromList (f x) xs
Run Code Online (Sandbox Code Playgroud)

让我们尝试自己推断类型。我们立即可以看出,第一个参数f应该是至少一个参数的函数,第二个参数(x:xs)是一个列表,并且列表元素应该与 的第一个参数具有相同的类型f。在第一种情况下,返回参数f,因此最终返回类型必须与第一个参数相同。所以我们从这个开始:

argsFromList :: (a -> ?) -> [a] -> (a -> ?)
Run Code Online (Sandbox Code Playgroud)

为了找到未知类型?,我们可以看第二种情况,它由递归调用组成。参数xs是相同的列表类型,并且参数的(f x)类型为?。由于它被用作递归调用中的第一个参数,其类型为(a -> ?),我们现在可以得出结论 ,它与 其?类型相同(a -> ?),因此与 其类型相同,因此与 其(a -> (a -> ?))类型相同...哎呀。(a -> (a -> (a -> ?)))

当然,这就是“无限类型”。

如果您想使用使用可变数量的单一类型参数的函数来执行此操作,您可能需要使用采用值列表而不是单个参数的函数。否则,您将不得不单独编写每个版本,或者使用一些涉及高级语言功能的神秘技巧,这在像这样的简单情况下都没有吸引力。