+5  A: 

tough love

sometime the best help is no help. good luck on your homework, don't forget to do it next time, get a calendar.

KM
In any other context I'd -1 this for being rude, but +1 for being blunt. :)
musicfreak
I really don't know how, it's not about the due date.
better to get tough love when you are still in school, than on the job...
KM
-1 This is not an answer to the question asked.
Chuck
@chuck, where's your answer?
KM
I don't have a good answer. Hence I didn't give one.
Chuck
-1, flagged as abusive! Stackoverflow should be a forum for recording and answering technical questions, not acting superior to people for asking questions. We've all forgotten things. It happens.
e5
@e5, I have 8 up and 6 down so far on this, and explain how this is "abusive"? you might not like it, but is isn't "abusive"
KM
I agree it's not abusive, but it's still something that belongs as a comment rather than an answer, because it ISN'T an answer.
Chuck
@Chuck: It happens pretty often on SO that an answer is "the antecedents of the question are false" rather than a direct solution. @KM: I agree, anyone who views this as "abusive" is far too sensitive and will be too offended by too many things to get any useful information from the Internet.
ephemient
@ephemient: Explaining that a question or its assumptions are flawed is an answer. Commenting on the asker's planning abilities, dress habits, sexuality, etc. is not an answer unless the question is about those things. This question is about writing a function in Haskell.
Chuck
@Chuck, you're right, next time I'll make a non-code response, I'll make it a comment. I just thought an answer would show that I stood by it, so people could vote it down if they wanted to. You can't vote down a comment.
KM
@KM: I see what you're saying. It just bothers me because of the opposite — people have a tendency to vote up things like this to say "I AGREE", which can sometimes leave actual answers kind of buried if they come a while later.
Chuck
@Chuck, the question title was "Haskell functions [urgent]" and the question started "I completely forgot about my Haskell project which is due in a couple of hours, any help would be appreciated." If my own kid posed that question to me, I would give them this same answer. This answer will help them more than the actual code. Better to have this problem in school, light a fire under their butt and get organized now, that get fired at a job.
KM
@e5: SO is also not a forum for asking about homework that's due in a couple hours.
musicfreak
+3  A: 

When I was in college my best friend was a pocket-sized dayrunner. Never forgot about homework, prioritized by nearest due date (they say that's most efficient).

Jason Catena
Heh, I always prioritized by "what's most fun?" This led to overachievement in CS and ruin in all other subjects :)
ephemient
A: 

I recommend iPhone and a good to-do list / Calendar for it. (Here is my honesty: I can't help with the assignment. Sorry but good luck)

Frank V
+13  A: 
ephemient
+2  A: 

The basic evaluate is pretty straight forward:

import Data.Maybe (fromJust)
import Data.List (nub)

type Variable = Char
data LogicExpr
   = Var Variable
   | Neg LogicExpr
   | Conj LogicExpr LogicExpr
   | Disj LogicExpr LogicExpr
   | Impl LogicExpr LogicExpr
   deriving (Eq, Ord)

-- evaluates an expression
evaluate :: LogicExpr -> [(Variable, Bool)] -> Bool
evaluate (Var v) bs      = fromJust (lookup v bs)
evaluate (Neg e) bs      = not (evaluate e bs)
evaluate (Conj e1 e2) bs = evaluate e1 bs && evaluate e2 bs
evaluate (Disj e1 e2) bs = evaluate e1 bs || evaluate e2 bs
evaluate (Impl e1 e2) bs = not (evaluate e1 bs) || evaluate e2 bs

To generate a truth table, you first have to find all the variables in an expression and then generate all the possible assignments for these variables. The truth values of these assignments can easily be determined with the already implemented evaluate function:

-- get variables in an expression
varsp :: LogicExpr -> [Variable]
varsp (Var v)      = [v]
varsp (Neg e)      = varsp e
varsp (Conj e1 e2) = varsp e1 ++ varsp e2
varsp (Disj e1 e2) = varsp e1 ++ varsp e2
varsp (Impl e1 e2) = varsp e1 ++ varsp e2

-- get variables in an expression without duplicates
vars :: LogicExpr -> [Variable]
vars = nub . varsp

-- possible boolean values
bools = [True, False]

-- all possible combinations of variable assignments
booltable :: [Variable] -> [[(Variable, Bool)]]
booltable [] = [[]]
booltable (a:as) = [(a,b) : r | b <- bools, r <- booltable as]

-- variable assignments and corresponding evaluation of an expression
truthtable :: LogicExpr -> [([(Variable, Bool)], Bool)]
truthtable e = [(bs, evaluate e bs) | bs <- booltable (vars e)]

If you want to explore the dark corners of the standard library, you can also write a Read instance for easy input of LogicExprs:

-- read a right-associative infix operator
readInfix opprec constr repr prec r
   = readParen (prec > opprec)
     (\r -> [(constr e1 e2, u) |
             (e1,s) <- readsPrec (opprec+1) r,
             (op,t) <- lex s,
             op == repr,
             (e2,u) <- readsPrec (opprec) t]) r

instance Read LogicExpr where
   readsPrec prec r
      =  readInfix 1 Impl "->" prec r
      ++ readInfix 2 Disj "|" prec r
      ++ readInfix 3 Conj "&" prec r
      ++ readParen (prec > 4)
         (\r -> [(Neg e, t) |
                 ("!",s) <- lex r,
                 (e,t)   <- readsPrec 4 s]) r
      ++ readParen (prec > 5)
         (\r -> [(Var v, s) |
                 ([v], s) <- lex r]) r

And truth tables can be printed prettily:

showcell :: (Variable, Bool) -> String
showcell (v,b) = v : "=" ++ show b

showrow :: [(Variable, Bool)] -> Bool -> String
showrow []     b = show b
showrow [a]    b = showcell a ++ " => " ++ show b
showrow (a:as) b = showcell a ++ " && " ++ showrow as b

printrow :: ([(Variable, Bool)], Bool) -> IO ()
printrow = putStrLn . uncurry showrow

printtbl :: [([(Variable, Bool)], Bool)] -> IO ()
printtbl = mapM_ printrow

All together truth tables can be generated like this:

Prelude Main> printtbl $ truthtable $ read "(a -> b) & (b -> a)"
a=True && b=True => True
a=True && b=False => False
a=False && b=True => False
a=False && b=False => True

Prelude Main> printtbl $ truthtable $ read "(a | b) | (!a & !b)"
a=True && b=True => True
a=True && b=False => True
a=False && b=True => True
a=False && b=False => True
sth