0

What I'm trying to do is that I want to take a list of strings as input and do some operations then return back a list of strings. The problem is, I am looking for specific yet generic patterns of the string for each case:

func :: [String] -> [String]
func [] = []
func [x] = [x]
func (["Not","(","Not"]:es:[")"]) = es  --HERE
func ("Not":"(":pred:"And":rest:")") = ("Not":pred:"Or":(pushNotInwards rest))
func ("Not":"(":pred:"Or":rest:")") = ("Not":pred:"And":(pushNotInwards rest))
func ("Not":"(":"ForAll":x:scope:")") = ("Exists":"Not":"("scope:")")
func ("Not":"(":"Exists":x:scope:")") = ("ForAll":"Not":"(":scope:")")

For the third case for instance, I want to take a list of strings in the form of:

["Not","(","Not",some_strings,")"]

I tried using ++ on the left hand side as:

func (["Not"]++["("]++["Not"])++es++[")"]) = es

I also tried concat and : but they didn't work either. Any suggestions?

1
  • 2
    You should do the pattern matching properly: func ("Not(Not": es : [")"]) = [es]. Commented Nov 26, 2014 at 12:43

2 Answers 2

3

You seem to have some confusion about the different string operators.

A String is just a synonym for a list of chars i.e. [Char]. The colon : operator (aka cons) adds one element to the beginning of a list. Here's its type:

*Main> :t (:)
(:) :: a -> [a] -> [a]

For example:

*Main> 1:[2,3]
[1,2,3]
*Main> 'a':"bc"
"abc"

The ++ operator concatenates two lists. Here's its type:

*Main> :t (++)
(++) :: [a] -> [a] -> [a]

Pattern matching can only be done using a data constructor. The : operator is a data constructor, but the ++ operator is not. So you cannot define a function using pattern matching over the ++ operator.

To define a function using pattern matching, I'd suggest defining a new data type for the different functions and qualifier rather than using strings:

-- Logic Operation
data LogicOp =
    Not LogicOp | And [LogicOp] | Or [LogicOp] |
    Forall String LogicOp | Exists String LogicOp | T | F
  deriving (Eq, Show)

func :: LogicOp -> LogicOp
func (Not (Not x)) = x
func (Not (And (pred:rest))) = Or (Not pred:[func (Not (And rest))])
func (Not (Or  (pred:rest))) = And (Not pred:[func (Not (Or rest))])
func (Not (Forall x scope)) = Exists x (Not scope)
func (Not (Exists x scope)) = Forall x (Not scope)
func x = x

Here are some examples:

*Main> func (Not (Not T))
T
*Main> func (Not (And [T, F, T]))
Or [Not T,Or [Not F,Or [Not T,Not (And [])]]]
*Main> func (Not (Or [T, F, T]))
And [Not T,And [Not F,And [Not T,Not (Or [])]]]
*Main> func (Not (Forall "x" (And T F))
*Main> func (Not (Forall "x" (And [T, F])))
Exists "x" (Not (And [T,F]))
*Main> func (Not (Exists "x" (And [T, F])))
Forall "x" (Not (And [T,F]))
Sign up to request clarification or add additional context in comments.

2 Comments

That was very helpful! I tried implementing FOL using objects at first but I had problems when I wanted to create Atoms, Vars and predicates to be part of the expression. Do you think I can integrate them in your solution?
I think so. Atoms would be the F and T constructors, vars could be just strings, or you could define a new data type data Var = Var String. In this case, the universal and existential quantifiers would accept Var instead of String as their binding variable. Predicates would possibly be a new data constructor Predicate (LogicOp -> LogicOp).
2

You should probably not use strings for that. Create a new type:

 data SomeExpr = Not SomeExpr
               | And SomeExpr SomeExpr
               | Or  SomeExpr SomeExpr
               deriving (Show)

Then you could match on that expression:

 func :: SomeExpr -> SomeExpr
 func (Not (Not x)) = func x
 func (Not (And x y)) = Or (Not $ func x) (Not $ func y)
 func (Not (Or  x y)) = And (Not $ func x) (Not $ func y)
 ...
 func x = x

You can't pattern match a list in the middle, e.g You want to match [1,2,3,4,5] with (1:middle:5:[]), but this is invalid.

Yes, using an own type has it's own problems, you have to parse it etc, but it is much more easier and safer than with strings (which could have arbitrary content).

2 Comments

I am actually implementing FOL as you might have noticed and I got stuck when I tried implementing it using objects because I found them hardly manipulated in Haskell. There's too much recursion.You have a good point. I will consider it again.
Just a few hints: you can implement your own show for this type and convert And x y to x and y. Parsec is a great library for parsing stuff.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.