Márquez
Márquez

Reputation: 101

Propositional logic in haskell

I have the following data types

data Prop =
  Var Name
  | Neg Prop
  | Conj Prop Prop
  | Disy Prop Prop
  | Impl Prop Prop
  | Syss Prop Prop deriving Show -- if and only if

-- And the following

type Name = String

type State = (Name, Bool) -- The state of a proposition, Example ("P", True), ("Q", True)

type States = [State] -- A list of states, [("P", True), ("Q", False), ...]

type Row = (States, Bool) -- A row of the table. ([("P", True), ("Q", False), ...], True)

type Table = [Row]

The case is that I want to generate all the possible states of a proposition

P, Q, R

1 1 1

1 1 0

1 0 1

...

To do this, I create auxiliary functions to gradually build the states

-- Get all the atoms of a proposition
varList :: Prop -> [Name] 
varList (Var p) = [p]
varList (Neg p) = varList p
varList (Conj p q) = varList p ++ varList q
varList (Disy p q) = varList p ++ varList q
varList (Impl p q) = varList p ++ varList q
varList (Syss p q) = varList p ++ varList q

--Power set to get all values 
conjPoten :: Eq a => [a] -> [[a]]
conjPoten []     = [[]]
conjPoten (x:xs) = map (x: ) pt `union` pt
  where
    pt = conjPoten xs


-- Give value to a proposition, "P" -> True, "" -> False 
giveValue:: Name -> Bool
giveValue p = p /= []

-- Generate a State, "P" -> ("P",True), "" -> ("",False)
generateState :: Name -> State
generateState p = (p , daValor p)


-- The function that I want
generateStates:: [Name] -> States
generateStates p = [(a,True) | a <-p]

This, of course, is a test to verify that "it works", because if generateStates ["P","Q", "R"] = [("P",True),("Q",True),("R",True)]

I did this thinking that in the power set we are going to have cases like ["P","Q","R"] and ["P","Q"], that is, there is not going to be "R". So the intention is that ["P","Q","R"] gives us [("Q",True),("P",True),("R",True)] and ["P","Q"] gives us [("Q",True),("P",True),("R",False)]

But from here I have two questions The first is, that I have to modify the second element of the tuple, so what I came up with was

generateStates :: [Name] -> States
generateStates p = [ (a, b) | a<- p, a<- giveValue p]

The main error that the prelude marks me is: Couldn't match type ‘[Char]’ with ‘Char’

Which I understand, because p is a list and giveValue works with a Name, not with a list of Names

I tried to do it like

generateStates :: [Name] -> States
generateStates [p] = [ (p, b) | a<- giveValue p]

But that tells me: Couldn't match expected type ‘[Bool]’ with actual type ‘Bool’ Which, now I don't understand, plus it tells me there aren't enough patterns

The other question is that, having

generateStates :: [Name] -> States
generateStates p = [ (a, True) | a<-p]

and try it with generateStates ["P","Q"] would only give me [("Q",True),("P",True)] But we have P, Q and R, so I'm missing the ("R", False) But since it is in the arguments that we pass, it cannot add it to the list

Thanks!

Upvotes: 2

Views: 307

Answers (1)

Olav Aga
Olav Aga

Reputation: 143

To change the tuple, you really create a new one, as they are not mutable. You could create a function using pattern matching. The below function works on pairs (tuples with two elements).

modTuple (firstValue, secondValue) updatedValue = (firstValue, updatedValue)

Alternatively you could access the members of the tuple with the built-in fst and snd to access the first and second elements, and create a new tuple.

You can use pattern matching to access individual elements of a list, and build up States recursively. I.e.

generateStates [] = []
generateStates (p:ps) = (p, giveValue p):(generateStates ps)

Upvotes: 1

Related Questions