Convert a Haskell function to SML - haskell

I'm trying to convert a Haskell function, which displays a boolean formula, to a SML function.
The function:
data Formula
= Atom String
| Neg Formula
| Conj Formula Formula
| Disj Formula Formula
precedence :: Formula -> Int
precedence Atom{} = 4
precedence Neg {} = 3
precedence Conj{} = 2
precedence Disj{} = 1
displayPrec :: Int -> Formula -> String
displayPrec dCntxt f = bracket unbracketed where
dHere = precedence f
recurse = displayPrec dHere
unbracketed = case f of
Atom s -> s
Neg p -> "~ " ++ recurse p
Conj p q -> recurse p ++ " & " ++ recurse q
Disj p q -> recurse p ++ " | " ++ recurse q
bracket
| dCntxt > dHere = \s -> "(" ++ s ++ ")"
| otherwise = id
display :: Formula -> String
display = displayPrec 0
I' ve come so far as translating it to SML:
fun precedence(operator) =
case operator of
Atom a => 4
| Neg p => 3
| Conj(p,q) => 2
| Disj(p,q) => 1
fun displayPrec dCntxt f =
let
val dHere = precedence f
val recurse = displayPrec dHere
val unbracketed = case f of
Atom a => a
| Neg p => "~ " ^ recurse p
| Conj(p,q)=>(recurse p) ^ " & " ^ (recurse q)
| Disj(p,q)=>(recurse p) ^ " | " ^ (recurse q)
(* missing bracket function *)
in
(* bracket *) unbracketed
end
The unbracketed function works. It shows the formula without braces. The only thing that is still missing is the bracket function, which I don't know what it does and how to translate it to SML. Can someone, who is more experienced, help me with this?

That would be
val bracket =
if dCntxt > dHere
then fn s => "(" ^ s ^ ")"
else fn x => x
The function compares the precedence level of your context against the precedence level of the outer operator of your expression and decides to either insert a pair of parentheses around the given string or not.

Related

Swapping 2 characters in list of strings (Haskell)

I need to swap blank space with letter from "moves" and each time I swap it I need to continue with another one from moves. I get Couldn't match expected type, even though I just want to return value x when it doesn't meet condition.
Error message:
[1 of 1] Compiling Main ( puzzlesh.hs, interpreted )
puzzlesh.hs:19:43: error:
• Couldn't match expected type ‘Int -> a’ with actual type ‘Char’
• In the expression: x
In the expression: if x == ' ' then repl x else x
In an equation for ‘eval’: eval x = if x == ' ' then repl x else x
• Relevant bindings include
eval :: Char -> Int -> a (bound at puzzlesh.hs:19:5)
repl :: forall p. p -> Int -> a (bound at puzzlesh.hs:20:5)
moves :: [a] (bound at puzzlesh.hs:16:9)
p :: t [Char] -> [a] -> [Int -> a] (bound at puzzlesh.hs:16:1)
|
19 | eval x = if x == ' ' then repl x else x
| ^
Failed, no modules loaded.
Code:
import Data.Char ( intToDigit )
sample :: [String]
sample = ["AC DE",
"FBHIJ",
"KGLNO",
"PQMRS",
"UVWXT"]
moves = "CBGLMRST"
type Result = [String]
pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))
p input moves = [eval x | x <- (concat input)]
where
c = 1
eval x = if x == ' ' then repl x else x
repl x count = moves !! count
count c = c + 1
I need to take character from moves, replace it onto blank space and do this till moves is []
Desired output:
ABCDE
FGHIJ
KLMNO
PQRST
UVWX
As with most problems, the key is to break it down into smaller problems. Your string that encodes character swaps: can we break that into pairs?
Yes, we just need to create a tuple from the first two elements in the list, and then add that to the result of calling pairs on the tail of the list.
pairs :: [a] -> [(a, a)]
pairs (x:tl#(y:_)) = (x, y) : pairs tl
pairs _ = []
If we try this with a string.
Prelude> pairs "CBGLMRST"
[('C','B'),('B','G'),('G','L'),('L','M'),('M','R'),('R','S'),('S','T')]
But you want a blank space swapped with the first character:
Prelude> pairs $ " " ++ "CBGLMRST"
[(' ','C'),('C','B'),('B','G'),('G','L'),('L','M'),('M','R'),('R','S'),('S','T')]
Now you have a lookup table with original characters and their replacements and the rest is straightforward. Just map a lookup on this table over each character in each string in the list.
Because you never touch any letter in the original strings more than once, you won't have to worry about double replacements.
Prelude> s = ["AC DE","FBHIJ","KGLNO","PQMRS","UVWXT"]
Prelude> r = "CBGLMRST"
Prelude> r' = " " ++ r
Prelude> p = pairs r'
Prelude> [[case lookup c p of {Just r -> r; _ -> c} | c <- s'] | s' <- s]
["ABCDE","FGHIJ","KLMNO","PQRST","UVWXT"]

create a haskell function that returns the definition of a Haskell function that implements the expression

if I have the following data type
data Exp = Var String | Num Integer | OpExp Op Exp Exp data Op = Plus | Times | Minus
I would like to create code that takes a name and an Exp and returns the definition of a haskell function that implements the expression. for simplicity, lets assume it will only contain the variables "x" or "y"
so an example of what I am trying to accomplish
Lib> compile "foo" $ OpExp Times (Num 10) (OpExp Plus (Var "x") (Var "y"))
which would return:
"foo x y = (10 * (x + y))"
and this is what I have defined so far
compile :: String -> Exp -> String
compile name exp = name + " x y = undefined"
compile :: String -> Exp -> String
compile name exp = name ++ " x y = " ++(exp2string exp)
exp2string:: Exp -> String
exp2string (Var s) = s
exp2string (Num i) = show i
exp2string (OpExp o e1 e2) ="(" ++ (exp2string e1) ++ (op2string o) ++(exp2string e2) ++ ")"
op2string:: Op -> String
op2string Plus = " + "
op2string Times = " * "
op2string Minus = " - "

Trying to understand indentations in haskell

I am trying to make a program that solves the tower of hanoi. I made it a bit complicated just for exercise:
hanoi :: [Int] -> String
hanoi n
| n > 0 = hanoi' n "1" "2" "3"
where hanoi' n a b c
| n == 0 = "|"
| otherwise = let pre = hanoi' (n-1) a c b
posle = hanoi' (n-1) b c a
in pre ++ a ++ " ~~> " ++ c ++ posle
| otherwise = "Number must be greater than 0!!!"
But i get:
hanoi.hs:7:97: parse error on input ‘=’
Can someone please explain to me what is going on? I see now that i don't understand an important part of the language.
Your where has to come after all guards.
hanoi :: [Int] -> String
hanoi n
| n > 0 = hanoi' n "1" "2" "3"
| otherwise = "Number must be greater than 0!!!"
where hanoi' n a b c
| n == 0 = "|"
| otherwise = let pre = hanoi' (n-1) a c b
posle = hanoi' (n-1) b c a
in pre ++ a ++ " ~~> " ++ c ++ posle
This is stated in 4.4.3, although it's somewhat hidden if you're not used to BNF-like syntax:
decl → (funlhs | pat) rhs
funlhs → var apat { apat }
| pat varop pat
| ( funlhs ) apat { apat }
rhs → = exp [where decls]
| gdrhs [where decls]
gdrhs → guards = exp [gdrhs]
guards → | guard1, …, guardn (n ≥ 1)
guard → pat <- infixexp (pattern guard)
| let decls (local declaration)
| infixexp (boolean guard)
rhs is the important token. It's the only part that contains the optional where. A guard may only contain expressions and be followed by other guards.

Better display of boolean formulas

I want to implement a method for showing a propositional formula in SML. The solutions that I found so far was of this type:
fun show (Atom a) = a
| show (Neg p) = "(~ " ^ show p ^ ")"
| show (Conj(p,q)) = "(" ^ show p ^ " & " ^ show q ^ ")"
| show (Disj(p,q)) = "(" ^ show p ^ " | " ^ show q ^ ")";
This produces unnecessary braces:
((~p) & (q | r))
when, what I'd like to have is:
~ p & (q | r)
I saw, that Haskell has a function (display?) which does this nicely. Can someone help me out a little bit. How should I go about this?
If you want to eliminate redundant parentheses, you will need to pass around some precedence information. For example, in Haskell, the showsPrec function embodies this pattern; it has type
showsPrec :: Show a => Int -> a -> String -> String
where the first Int argument is the precedence of the current printing context. The extra String argument is a trick to get efficient list appending. I'll demonstrate how to write a similar function for your type, though admittedly in Haskell (since I know that language best) and without using the extra efficiency trick.
The idea is to first build a string that has no top-level parentheses -- but does have all the parentheses needed to disambiguate subterms -- then add parentheses only if necessary. The unbracketed computation below does the first step. Then the only question is: when should we put parentheses around our term? Well, the answer to that is that things should be parenthesized when a low-precedence term is an argument to a high-precedence operator. So we need to compare the precedence of our immediate "parent" -- called dCntxt in the code below -- to the precedence of the term we're currently rendering -- called dHere in the code below. The bracket function below either adds parentheses or leaves the string alone based on the result of this comparison.
data Formula
= Atom String
| Neg Formula
| Conj Formula Formula
| Disj Formula Formula
precedence :: Formula -> Int
precedence Atom{} = 4
precedence Neg {} = 3
precedence Conj{} = 2
precedence Disj{} = 1
displayPrec :: Int -> Formula -> String
displayPrec dCntxt f = bracket unbracketed where
dHere = precedence f
recurse = displayPrec dHere
unbracketed = case f of
Atom s -> s
Neg p -> "~ " ++ recurse p
Conj p q -> recurse p ++ " & " ++ recurse q
Disj p q -> recurse p ++ " | " ++ recurse q
bracket
| dCntxt > dHere = \s -> "(" ++ s ++ ")"
| otherwise = id
display :: Formula -> String
display = displayPrec 0
Here's how it looks in action.
*Main> display (Neg (Conj (Disj (Conj (Atom "a") (Atom "b")) (Atom "c")) (Conj (Atom "d") (Atom "e"))))
"~ ((a & b | c) & d & e)"

Haskell syntax for 'or' in case expressions

In F#, I can use | to group cases when pattern matching. For example,
let rec factorial n =
match n with
| 0 | 1 -> 1 // like in this line
| _ -> n * factorial (n - 1)
What's the Haskell syntax for the same?
There is no way of sharing the same right hand side for different patterns. However, you can usually get around this by using guards instead of patterns, for example with elem.
foo x | x `elem` [A, C, G] = ...
| x `elem` [B, D, E] = ...
| otherwise = ...
with guards:
factorial n
| n < 2 = 1
| otherwise = n * (factorial (n - 1))
with pattern matching:
factorial 0 = 1
factorial 1 = 1
factorial n = n * (factorial (n - 1))
I'm not entirely familiar with F#, but in Haskell, case statements allow you to pattern match, binding variables to parts of an expression.
case listExpr of
(x:y:_) -> x+y
[x] -> x
_ -> 0
In the theoretical case that Haskell allowed the same:
It would therefore be problematic to allow multiple bindings
case listExpr of
(x:y:_) | [z] -> erm...which variables are bound? x and y? or z?
There are rare circumstances where it could work, by using the same binding:
unEither :: Either a a -> a
unEither val = case val of
Left v | Right v -> v
And as in the example you gave, it could work alright if you only match literals and do not bind anything:
case expr of
1 | 0 -> foo
_ -> bar
However:
As far as I know, Haskell does not have syntax like that. It does have guards, though, as mentioned by others.
Also note:
Using | in the case statement serves a different function in Haskell. The statement after the | acts as a guard.
case expr of
[x] | x < 2 -> 2
[x] -> 3
_ -> 4
So if this sort of syntax were to be introduced into Haskell, it would have to use something other than |. I would suggest using , (to whomever might feel like adding this to the Haskell spec.)
unEither val = case val of
Left v, Right v -> v
This currently produces "parse error on input ,"
Building on some of the above answers, you can (at least now) use guards to do multiple cases on a single line:
case name of
x | elem x ["Bob","John","Joe"] -> putStrLn "ok!"
"Frank" -> putStrLn "not ok!"
_ -> putStrLn "bad input!"
So, an input of "Bob", "John", or "Joe" would give you an "ok!", whereas "Frank" would be "not ok!", and everything else would be "bad input!"
Here's a fairly literal translation:
factorial n = case n of
0 -> sharedImpl
1 -> sharedImpl
n -> n * factorial (n - 1)
where
sharedImpl = 1
View patterns could also give you a literal translation.
isZeroOrOne n = case n of
0 -> True
1 -> True
_ -> False
factorial1 n = case n of
(isZeroOrOne -> True) -> 1
n -> n * factorial (n - 1)
factorial2 n = case n of
(\n -> case n of { 0 -> True; 1 -> True; _ -> False }) -> 1
n -> n * factorial (n - 1)
Not saying that these are better than the alternatives. Just pointing them out.

Resources