简体   繁体   中英

haskell: a disjunctive normal form function

I'm trying to create a function which will change a proposition into disjunctive normal form.

It will do this by reading in a list of Valuation :

type Valuation = [(Variable, Bool)] -- Valuation of variables to truth values 

and using these:

findBool :: (Variable, Bool)->Bool
findBool (_,x) = x

findVar :: (Variable, Bool)->Variable
findVar (x,_) = x

Also Proposition is:

data Prop = Falsum         -- a contradiction, or
          | Var Variable   -- a variable, or
          | Not Prop       -- a negation of a formula, or
          | Or  Prop Prop  -- a disjunction of two formulae, or
          | And Prop Prop  -- a conjunction of two formulae, or
          | Imp Prop Prop  -- a conditional of two formulae.
            deriving (Eq, Show)

I think what I have so far is pretty solid but I can't see what to do for the empty case. Here's what I have so far:

minterm :: Valuation -> Prop
minterm [] = ?
minterm (x:xs) = if (findBool x) then (And (findVar x) (minterm xs)) else (And (Not(findVar x) (minterm xs)) 

my goal is for: minterm [("p",True),("q",False)] to return: And (Var "p") (Not (Var "q"))

edit: Not Falsum works but I'd prefer if it didn't return anything. Is there anyway I can exclude cases where it would be returned so I can get something like this:

minterm [("p",True),("q",False)] == And (Var "p") (Not (Var "q"))

The standard way to return nothing is to return Nothing .

minterm :: Valuation -> Maybe Prop
minterm []     = Nothing
minterm (x:xs) =
    Just $ case minterm xs of
             Nothing -> y
             Just mt -> And y mt
  where
    y = if (findBool x)
            then findVar x
            else Not $ findVar x

Notice that now your top-level type signature will reflect this notion of failure.

Based on your edit, is it possible you just want to special case the ending to tidy it up?

minterm :: Valuation -> Prop
minterm [] = Not Falsum
minterm [x] = oneTerm x
minterm (x : xs) = And (oneTerm x) (minterm xs)

oneTerm (x, True) = Var x
oneTerm (x, False) = Not (Var x)

You could change your minterm function to return a list of clauses instead of a term:

minterm :: Valuation -> [Prop]
minterm [] = []
minterm (x:xs) = if (findBool x) then findVar x : minterm xs else Not (findVar x)  : minterm xs

and then write another function to convert it into a Prop:

and :: [Prop] -> Prop
and [] = Not Falsum
and xs = foldr1 And xs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM