Not in scope: data constructor - haskell

I wrote a program with haskell but I got errors from ghci
here is the source codes,I construct it, and if I have
p1 :: Prop
p1 = And (Var 'A') (Not (Var 'A'))
It will show A && ~A so that is the source codes
import Data.List
import Data.Char
data Prop = Const Bool |
Var Char |
Not Prop |
And Prop Prop |
Or Prop Prop |
Imply Prop Prop
deriving Eq
instance Show Prop where
show (Var Char) = show Char
show (Not Prop) = "(~" ++ show Prop ++ ")"
show (And Prop Prop) = "(" ++ show Prop ++ "&&" ++ show Prop ++ ")"
show (Or Prop Prop) = "(" ++ show Prop "||" ++ show Prop ++ ")"
show (Imply Prop Prop) = "(" ++ show Prop "=>" show Prop ++ ")"
And I got two main errors from ghci...
Not in scope: data constructor `Char'
Not in scope: data constructor `Prop'
I am a beginner with haskell,thankyou very much.

Value names that start with an uppercase letter are reserved for constructors, like Var, True, False, etc. Variables must start with a lowercase letter.
Additionally, you can't use the same name for two different variables. How would Haskell know which one you meant each time you used them? You can't simply use the definition of a constructor as a pattern in a function; you need to give a separate name to each field.
So, instead of Var Char, write Var name; instead of Imply Prop Prop, write Imply p q (or Imply prop1 prop2), and so on.

A slight edit will get it working:
instance Show Prop where
show (Var c) = [c]
show (Not p) = "(~" ++ show p ++ ")"
show (And p1 p2) = "(" ++ show p1 ++ " && " ++ show p2 ++ ")"
show (Or p1 p2) = "(" ++ show p1 ++ "||" ++ show p2 ++ ")"
show (Imply p1 p2) = "(" ++ show p1 ++ "=>" ++ show p2 ++ ")"

Related

Turn a data type into a String for display without `show`

This question has me absolutely puzzled. The goal is to take a specific data type and use it to create a string. The data type is:
data Math = Val Int
| Add Math Math
| Sub Math Math
| Mult Math Math
| Div Math Math
deriving Show
This example:
ex1 :: Math
ex1 = Add1 (Val1 2) (Val1 3)
should output "2 + 3" with the correct code.
I wrote the following code and realized I was having two issues:
show :: Math -> String
show (Val n) = show n
show (Add e1 e2) = show e1 ++ " + " ++ show e2
show (Sub e1 e2) = show e1 ++ " - " ++ show e2
show (Mult e1 e2) = show e1 ++ " * " ++ show e2
show (Div e1 e2) = show e1 ++ " / " ++ show e2
The curve ball is that the function MUST be named show, as it is - so calling show from Prelude won't work. My first thought it to create a helper that turns every value into a literal but, again, I have no idea how to do that without show for a data type. I legitimately have no idea what direction to head in.
You're almost there! To keep show from the Prelude from interfering, add
import Prelude hiding (show)
to the top of your file.
But then, you'll need access to Prelude's show after all, so that you can show the Int inside your Val. So also add this:
import qualified Prelude (show)
With those two lines, you can write:
show :: Math -> String
show (Val n) = Prelude.show n
show (Add e1 e2) = show e1 ++ " + " ++ show e2
show (Sub e1 e2) = show e1 ++ " - " ++ show e2
show (Mult e1 e2) = show e1 ++ " * " ++ show e2
show (Div e1 e2) = show e1 ++ " / " ++ show e2
and you should have what you want.
Alternatively, if you want to be implementing Show the class instead of a standalone, identically (and confusingly) named show function, the code you have for show works as-is. You just need to put it inside an instance definition, like this:
instance Show Math where
show (Val n) = show n
-- etc...
You can either disable the show method defined by Show:
import Prelude hiding (show)
or you can explicitly refer to show defined in your module. Assuming it is defined in Main,
main = putStrLn $ Main.show (Val 3)

Haskell - Iterate Tuple with Different Functions

I have been trying to to iterate the cand data in order to apply a function "pt_string".
Pt :: (Float, Float)
Person :: (Pt, Pt, [Pt], Float)
My idea is to call that function "pt_string" in a different way for each element of the tupple.
For example:
pt_string Point (first)
map pt_string [Point]
pt_string Point (second)
show "Tmp"
So far, I got:
pt_string :: pt -> String
pt_string pt = "(" ++ show (fst pt) ++ "," ++ show (snd pt) ++ ")\n"
Which works fine. But how can I create cand_to_string :: cand -> String in the above order?
Thanks!
Assuming
type Candidate = (Point, Point, [Point], Float)
you can use
candidate_to_string :: Candidate -> String
candidate_to_string (p1, p2, ps, f) =
"(" ++
point_to_string p1 ++ ", " ++
point_to_string p2 ++ ", " ++
points_to_string ps ++ ", " ++
show f ++
")"
which relies on
points_to_string :: [Point] -> String
points_to_string ps = "[" ++ intercalate ", " (map point_to_string ps) ++ "]"
exploiting Data.List.intercalate to add commas between the points.
Also note that, if you simply want the standard list/tuple printing format, you can directly use
candidate_to_string :: Candidate -> String
candidate_to_string = show

mapping multiple functions in haskell

I'm working on a way of representing memory in Haskell that looks like this...
data MemVal = Stored Value | Unbound
deriving Show
type Memory = ([Ide],Ide -> MemVal)
As an Identifier is called its added to the list of Identifiers. If an error occurs in the program I want to be able to recall the identifiers used up to date. So far I have this...
display :: Memory -> String
display m = "Memory = " ++ show (map (snd m) (fst m)) ++ " "
But was wondering if there were a way to map the name of the identifier to (fst m) as well as the function (snd m) so the output will be similar to...
Memory = [sum = stored Numeric 1, x = stored Boolean true]
Thank you.
You probably want something like this
display :: Memory -> String
display (ides, mem) =
"Memory = [" ++ unwords (map (\x -> x ++ "=" ++ mem x) ides) ++ "]"
I'm guessing this is what you are after:
import Data.List (intercalate)
display (Memory ids f) = "Memory = [" ++ (intercalates ", " assigns) ++ "]"
where assigns = [ show i ++ " = " ++ show (f i) | i <- ids ]
Here assigns is a list like:
[ "sum = stored Numeric 1", "x = stored Boolean true", ...]
and intercalate ", " assigns joins the strings together.
I've used destructuring to avoid having to refer to fst ... and snd ...

Haskell - how to change the show to get the right output

I have defined these datatypes which I am trying to create and print now.
type TNonTerminal = String -- will be creating own ones where [A-Z] won't be enough
type TTerminals = Char
type TSymbols = String -- both terminals and nonterminals
data Rule = Rule
{ leftSide :: TNonTerminal
, rightSide :: [TSymbols]
} deriving (Eq)
data RightLinearGrammar = RLG
{ nonterminals :: [TNonTerminal]
, terminals :: [TTerminals]
, firstNonterminal :: TNonTerminal
, rules :: [Rule]
} deriving (Eq)
So I also created those Show instances
instance Show Rule where
show (Rule ls rs) = show ls ++ "->" ++ show rs ++ "\n"
instance Show RightLinearGrammar where
show (RLG n t fn r) = show n ++ "\n" ++ show t ++ "\n" ++ show fn ++ "\n" ++ show r ++ "\n"
And I get this output (for clarification I created the Type RightLinearGrammar and called putStr $ show rlg):
["A","B"] -- [TNonTerminal]
"abc" -- [TTerminals]
"A" -- TNonTerminal
["A"->["aaB"] --
,"A"->["ccB"]
,"B"->["bB"] -- [Rule]
,"B"->["#"]
] --
How should I change the code to get better output like this one?
A,B
a,b,c
A
A->aaB
A->ccB
B->bB
B->#
show is by default going to give you quotes around strings and brackets around lists. If you just go back to concatenating strings and joining lists with commas or newlines, you should get the output you're expecting:
import Data.List (intercalate)
instance Show Rule where
show (Rule ls rs) = ls ++ "->" ++ intercalate "," rs
instance Show RightLinearGrammar where
show (RLG n t fn r) = intercalate "," n ++ "\n" ++ t ++ "\n" ++ fn ++ "\n" ++ (intercalate "\n" $ map show r) ++ "\n"
You either need to replace your type synonyms with newtypes, and define show on them to do what you want, or more likely replace the calls to show in your instances with calls to a custom formatter function.
Note: show is really not the right function for what you're trying to do, since it usually produces output you could paste back into ghci and arguably should be limitted to that use. You could easily define your own function and use it like this:
formatRule :: Rule -> String
formatRule (Rule ls rs) = ls ++ "->" ++ concat (intersperse "," rs) ++ "\n"
formatRightLinearGrammar :: RightLinearGrammar -> String
formatRightLinearGrammar (RLG n t fn r) =
concat (intersperse "," n) ++ "\n"
++ intersperse ',' t ++ "\n"
++ fn ++ "\n"
++ concat (map formatRule r)
Note: this is going to be fairly inefficient for large grammars; you might want to consider re-writing it as
formatRule :: Rule -> String -> String
formatRule (Rule ls rs) = (ls++) . ("->"++) . concatDS (intersperse "," rs) . ("\n"++)
formatRightLinearGrammar :: RightLinearGrammar -> String
formatRightLinearGrammar (RLG n t fn r) =
concatDS (intersperse "," n) $ ("\n"++) $
(intersperse ',' t ++) $ ("\n"++) $
(fn++) $ ("\n"++) $
foldr formatRule "" r
concatDS ss s' = foldr (++) s' ss

Haskell show definition for custom datatype has inconsistent use of leading quotations

Here's a simplified version of the code I'm working on
data ArithExp = Con Int
| Add ArithExp ArithExp
instance Show ArithExp where
show (Con i) = show i
show (Add e1 e2) = show "( " ++ show e1 ++ " + " ++ show e2 ++ " )"
So, if I run the command
Add (Con 6) (Con 0)
The output I want is:
( 6 + 0 )
But the code above prints:
"( "6 + 0 )
As far as I can tell, the show function is printing the quotes in the first string as characters but then using them as correctly in the concatenation that follows. The behavior seems really inconsistent to me. Any insights that will help me get the right output would be greatly appreciated.
Thanks in advance!
In the (Add e1 e2) branch show is binding more tightly than (++), so your code is, more parenthetically,
show (Add e1 e2) = (show "( ") ++ (show e1) ++ " + " ++ (show e2) ++ " )"
The trick is that you don't really need that leading show---you're generating the string directly and only need show applied recursively to e1 and e2.
show (Add e1 e2) = "( " ++ show e1 ++ " + " ++ show e2 ++ " )"
In general, show will try to print your data in a way that, if you were to type it into ghci, it would evaluate to an equivalent data value. Think about what that means in the case of a string. How do you type a string value in such that Haskell interprets it as a string rather than an expression to evaluate?
Here's a sample ghci session illustrating what I mean:
> let myString = "Hello"
> putStrLn $ show myString
=> "Hello"
> :t "Hello"
=> "Hello" :: String
> putStrLn myString
=> Hello
> :t Hello
=> Not in scope: data constructor 'Hello'
Since you had to type your string in quotes originally so that it would evaluate to a string instead of a constructor expression, show will put quotes around it so you could paste the value back into ghci and get a string value instead of a constructor value.
While show's behavior may seem a little counter-intuitive in your example, it's actually very consistent in how it behaves. Hopefully knowing why it behaves this way will help you to avoid running into a problem like this in the future!

Resources