简体   繁体   中英

Reduce the size of a proposition in Haskell

There is a function simplify , where simplify :: Proposition -> Proposition , where

data Proposition =  Const Bool 
                   | Var String
                   | And Proposition Proposition
                   | Or Proposition Proposition
                   | Not Proposition
                   deriving Show

It is used to reduce the size of a given proposition.

For example,

simplify (Const False `And` a) == Const False 
simplify (Const True `And` a)  == a

My attempt is to use pattern matching in that case:

simplify (Const False `And` a) = Const False
simplify (Const False `Or` a) = Const False
simplify (Const False `Not` a) = Const False
simplify (Const True `And` a) = a
simplify (Const True `Or` a) = a
simplify (Const True `Not` a) = a
simplify prop = prop

But I am receiving two types of errors:

  1. The constructor 'Not' should have 1 argument, but has been given 2

  2. Variable not in scope: a :: Proposition

What am I doing wrong?

There are several things that can be improved in your approach.

First, there are a few errors in your function, as already pointed out in the commments, the 'Not' constructor only takes one argument so

simplify (Const False `Not` a) = Const False

and

simplify (Const True `Not` a) = a

will not work. In addition there are some logic errors,

simplify (Const False `Or` a) = Const False

and

simplify (Const True `Or` a) = a

are incorrect.

Once these are fixed, your function should properly simplify, but only on the top level of the proposition. In order to simplify the whole proposition you need to add recursive calls to each right side that includes a variable and add the missing cases that are currently covered by

simplify prop = prop

eg you should change your cases like

simplify (Const True `And` a) = a

to

simplify (Const True `And` a) = simplify a

and add cases like

simplify (a `And` b) = ((simplify a) `And` (Simplify b))

This way the function will go through the entire proposition and stop at the first level. One way to make sure you have all cases covered is to remove

simplify prop = prop

and make a case for each constructor. For the variables, you can just write

simplify (Var a) = (Var a)

and that will leave them as they are.

In addition, top level functions are expected to have type annotations, so consider adding

simplify :: Proposition -> Proposition

above your function declaration.

A minor nitpick: In cases like

simplify (Const False `And` a) = Const False

you don't need to bind a and can instead use a wildcard, like so:

simplify (Const False `And` _) = Const False

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