How to convert Int to String in Haskell - haskell

I want to create an expression that can be composed of variables or constants (such as mathematical expressions) so I created a newtype to represent those expressions as strings, but when using it on functions it does not work:
newtype Expr = Expr String deriving (Show)
constant :: Int -> Expr
constant n = show n
variable :: String -> Expr
variable v = v
the error I get is that the type Expr does not match with String, and I cant use the function show even though I defined it earlier. please help!

You have a newtype wrapper, but you're trying to use it as if it were a type synonym. You can either go all the way with type, by changing your first line to type Expr = String, or go all the way with newtype, by putting Expr $ right after the = in the definitions of constant and variable.

As pointed out in the other answer you are treating the newtype as a type synonym. Remember that newtype is now creating a wrapper around your String, so you need to use its type constructor ExprConstructor to instantiate it.
newtype Expr = ExprConstructor String deriving (Show)
constant :: Int -> Expr
constant = ExprConstructor . show
variable :: String -> Expr
variable = ExprConstructor

Related

Is there a better way to add attribute field into AST in Haskell?

At first, I have a original AST definition like this:
data Expr = LitI Int | LitB Bool | Add Expr Expr
And I want to generalize it so that each AST node can contains some extra attributes:
data Expr a = LitI Int a | LitB Bool a | Add (Expr a) (Expr a) a
In this way, we can easily attach attribute into each node of the AST:
type ExprWithType = Expr TypeRep
type ExprWithSize = Expr Int
But this solution makes it hard to visit the attribute field, we must use pattern matching and process it case by case:
attribute :: Expr a -> a
attribute e = case e of
LitI _ a -> a
LitB _ a -> a
Add _ _ a -> a
We can image that if we can define our AST via a product type of the original AST and the type variable indicating attribute:
type ExprWithType = (Expr, TypeRep)
type ExprWithSize = (Expr, Int)
Then we can simplify the attribute visiting function like this:
attribute = snd
But we know that, the attribute from the outmost product type will not recursively appears in the subtrees.
So, is there a better solution for this problem?
Generally speaking, When we want to extract common field of different cases of a recursive sum type, we met this problem.
You could "lift" the type of the Expr for example like:
data Expr e = LitI Int | LitB Bool | Add e e
Now we can define a data type like:
data ExprAttr a = ExprAttr {
expression :: Expr (ExprAttr a),
attribute :: a
}
So here the ExprAttr has two parameters, the expression, which is thus an Expression that has ExprAttr as in the tree, and attribute which is an a.
You can thus process ExprAttrs, which is an AST of ExprAttrs. If you want to use a "simple" AST, you can define a type like:
newtype SimExpr = SimExpr (Expr SimExpr)
You might want to take a look at Cofree where f will be your recursive data type after abstracting the concept of recursion as an f-algebra and a will be the type of your annotation.
Nate Faubion gave a very accesible talk about this and similar approaches and you can watch it here: https://www.youtube.com/watch?v=eKkxmVFcd74

Is there a way to prevent Data.Generics.Alloy.GenInstances from scanning Data.Text.Internal?

I need to do transformations on an AST; here's a portion of the AST:
data Expr
= BinExpr { beOp :: BinaryOp
, beLeft :: Expr
, beRight :: Expr }
| Name Text
| IntegerLit Integer
| StringLit Text
deriving (Data, Typeable)
And this is a fairly complex AST, so there are many types involved.
I'm using alloy to generate the generic transformations, specifically:
autoGen :: IO ()
autoGen = do
createDirectoryIfMissing True baseDir
writeInstancesTo inst doc imports targetFile
where
inst = allInstances GenWithoutOverlapped
doc = [genInstance (undefined :: Doc)]
imports = header ++ instanceImports
Now, this was fine when using String, but I'm trying to migrate to Data.Text. When the code generation runs, it's reading into the internals of Data.Text like so:
instance (Alloy ([(GHC.Types.Char)]) (f :- ops) BaseOp) =>
Alloy ((Data.Text.Internal.Text)) BaseOp (f :- ops) where
transform _ ops (Data.Text.Internal.pack a0)
= Data.Text.Internal.pack
(transform ops BaseOp (a0))
I believe pack is tied to GHC internals so that's not a valid pattern match, and regardless, having the code mucking with the internals of a Data.Text is liable to break the invariants. (Edit: it looks like there's an instance Data Text where gfoldl f z txt = z packf(unpack txt) declaration, but regardless, I don't need/want to traverse Text values.)
Is there a way to force Alloy to treat a type as atomic? I'm hoping to avoid a newtype to wrap Text as all the code working with ASTs would need to deal with it, which rather defeats the purpose of using generics to avoid boilerplate.
Maybe try this trick: we parameterize the Expr type to override the Data instance used for Text when deriving instances with alloy.
data Expr_ text
= BinExpr { beOp :: BinaryOp
, beLeft :: Expr_ text
, beRight :: Expr_ text }
| Name text
...
| StringLit text
The rest of the code base can use this synonym, hopefully without breaking too much with type inference issues.
type Expr = Expr_ Text
But for Data-generic operations, we use a newtype wrapper around Text and make it behave like a nullary constructor, hoping alloy doesn't need the result of gunfold (or perhaps you could make it behave like a string using pattern synonyms).
newtype DataText = DataText Text
instance Data DataText where
gunfold _ f _ = f undefined
...
autoGen will then specialize everything at DummyText.
Use Data.Coerce.coerce to easily convert between functions on Expr_ DataText and Expr.
coerce :: Expr_ DataText -> Expr
coerce :: Expr -> Expr_ DataText
coerce :: (Expr_ DataText -> Expr_ DataText) -> Expr -> Expr
This might be used to write instances of alloy's type classes for Expr, based on the instances that were derived from you. It's a bit of boilerplate, but hopefully it can be contained and hidden without affecting the rest of the code.

New type declaring functions?

I'm familiar with the newtype declaration:
newtype MyAge = Age {age :: Int} deriving (Show, Eq, Ord)
In this instance Age is an Int, however I've come across the code below and I can't understand it:
newtype Ages a = Ages {age :: String -> [(a,String)]}
This appears to be a function declaration? (takes string, returns list of tuples containing 'a' and string) - is this correct?
N.B I've just realized this is just basic record syntax to declare a function.
Additionally, I've tried to implement this type, but I must be doing something wrong:
newtype Example a = Example {ex :: Int -> Int}
myexample = Example {ex = (\x -> x + 1)}
This compiles, however I don't understand why as I haven't passed the 'a' parameter?
This appears to be a function declaration?
Yes. Specifically, String -> [(a,String)] is a function type. A newtype declaration is analogous to a simple wrapper around any given type. There's no restriction that says you can't make it based on a function type, and it works in exactly the same way.
Also remember that you can always replace newtype with data; in this case, thinking about the resulting type as a record type that has a field that is a function might be helpful; newtype is just a special, optimized case.
One other thing to mention is that your two lines also differ in that the second one is parametrized over a. This can of course be used with regular types:
newtype MyWrapper a = MyWrapper a
or a function type can be newtype-d without parametrisation
newtype MyFunction = MyFunction (Float -> Float)
You can also write the above using the record syntax that gives you the "getter" function as well.

Parsec parsing in Haskell

I have 2 parsers:
nexpr::Parser (Expr Double)
sexpr::Parser (Expr String)
How do I build a parser that tries one and then the other if it doesn't work? I can't figure out what to return. There must be a clever way to do this.
Thanks.
EDIT:
Adding a bit more info...
I'm learning Haskel, so I started with :
data Expr a where
N::Double -> Expr Double
S::String -> Expr String
Add::Expr Double -> Expr Double -> Expr Double
Cat::Expr String -> Expr String -> Expr String
then I read about F-algebra (here) and so I changed it to:
data ExprF :: (* -> *) -> * -> * where
N::Double -> ExprF r Double
S::String -> ExprF r String
Add::r Double -> r Double -> ExprF r Double
Cat::r String -> r String -> ExprF r String
with
type Expr = HFix ExprF
so my parse to:
Parser (Expr Double)
is actually:
Parser (ExprF HFix Double)
Maybe I'm biting off more than I can chew...
As noted in the comments, you can have a parser like this
nOrSexpr :: Parser (Either (Expr Double) (Expr String))
nOrSexpr = (Left <$> nexpr) <|> (Right <$> sexpr)
However, I think the reason that you are having this difficulty is because you are not representing your parse tree as a single type, which is the more usual thing to do. Something like this:
data Expr =
ExprDouble Double
| ExprInt Int
| ExprString String
That way you can have parsers for each kind of expression that are all of type Parser Expr. This is the same as using Either but more flexible and maintainable. So you might have
doubleParser :: Parser Expr
doubleParser = ...
intParser :: Parser Expr
intParser = ...
stringParser :: Parser Expr
stringParser = ...
exprParser :: Parser Expr
exprParser = intParser <|> doubleParser <|> stringParser
Note that the order of the parsers does matter and use can use Parsec's try function if backtracking is needed.
So, for example, if you want to have a sum expression now, you can add to the data type
data Expr =
ExprDouble Double
| ExprInt Int
| ExprString String
| ExprSum Expr Expr
and make the parser
sumParser :: Parser Expr
sumParser = do
a <- exprParser
string " + "
b <- exprParser
return $ ExprSum a b
UPDATE
Well, I take my hat off to you diving straight into GADTs if you are just starting with Haskell. I have been reading through the paper you linked and noticed this immediately in the first paragraph:
The jury is still out on whether the additional type-safety provided by GADTs is worth the added inconvenience of working with them.
There are three points worth taking away here I think. The first is simply that I would have a go with the simpler way of doing things first, to get an idea of how it works and why you might want to add more type safety, before trying to more complicated type theoretical stuff. That comment may not help so feel free to ignore it!
Secondly, and more importantly, your representation...
data ExprF :: (* -> *) -> * -> * where
N :: Double -> ExprF r Double
S :: String -> ExprF r String
Add :: r Double -> r Double -> ExprF r Double
Cat :: r String -> r String -> ExprF r String
...is specifically designed to not allow ill formed type expressions. Contrasted with mine which can, eg ExprSum (ExprDouble 5.0) (ExprString "test"). So the question you really want to ask is what should actually happen when the parser attempts to parse something like "5.0 + \"test\""? Do you want it to just not parse, or do you want it to return a nice message saying that this expression is the wrong type? Compilers are usually designed in multiple stages for this reason. The first pass turns the input into an abstract syntax tree (AST), and further passes annotate this tree with type judgements. This annotated AST can then be transformed into the semantic representation that you really want it in.
So in your case I would recommend two stages. first, parse into a dumb representation like mine, that will give you the correct tree shape but allow ill-typed expressions. Like
data ExprAST =
ExprASTDouble Double
| ExprASTInt Int
| ExprASTString String
| ExprASTAdd Expr Expr
Then have another function that will typecheck the ExprAST. Something like
typecheck :: ExprAST -> Maybe (ExprF HFix a)
(You could also use Either and return either the typechecked GADT or an error string saying what the problem is.) The further problem here is that you don't know what a is statically. The other answer solves this by using type tags and an existential wrapper, which you might find to be the best way to go. I feel like it might be simpler to have a top level expression in your GADT that all expressions must live in, so an entire parse will always have the same type. In the end there is usually only one program type.
My third, and last, point is related to this
The jury is still out on whether the additional type-safety provided by GADTs is worth the added inconvenience of working with them.
The more type safety, generally the more work you have to do to get it. You mention you are new to Haskell, yet this adventure has taken us right to the edge of what it is capable of doing. The type of the parsed expression cannot depend only on the input string in a Haskell function, because it does not allow for dependant types. If you want to go down this path, I might suggest you have a look at a language called Idris. A great introduction to what it is capable of can be found in this video, in which he constructs a typesafe printf.
The problem described looks to be using Parsec to parse into a GADT representation, for which probably the easiest solution would be parse into a monotype representation and then have a (likely partial) type checking phase to produce the well-typed GADT, if it can. The monotype representation could be an existential wrapper over a GADT term, with a type-tag to reify the GADT index.
EDIT: a quick example
Let's define a type for type-tags and an existential wrapper:
data Type :: * -> * where
TDouble :: Type Double
TString :: Type String
data Judgement f = forall ix. Judgement (f ix) (Type ix)
With the example GADT given in the original post, we only have a problem with the outer-most production, which we need to parse to a monotype as we don't know statically which expression type we will get at runtime:
pExpr :: Parser (Judgement Expr)
pExpr = Judgement <$> pDblExpr <*> pure TDouble
<|> Judgement <$> pStrExpr <*> pure TString
We can write a type check phase to produce a GADT or fail, depending on whether the type assertion succeeds or not:
typecheck :: Judgement Expr -> Type ix -> Maybe (Expr ix)
typecheck (Judgement e TDouble) TDouble = Just e
typecheck (Judgement e TString) TString = Just e
typecheck _ _ = Nothing

Using Data.Typeable's cast with a locally defined data type

I have a data type which I'm using to represent a wxAny object in wxHaskell, currently I only support wxAnys which contain a String or an Int, thus:
data Any
= IsString String
| IsInt Int
| IsUndefined
I need a function (a -> Any) and I'm wondering if I can do it elegantly using Data.Typeable, or if anyone can suggest another approach?
You can do it relatively simply by combining the cast function with pattern guards:
f :: Typeable a => a -> Any
f x
| Just s <- cast x = IsString s
| Just n <- cast x = IsInt n
| otherwise = IsUndefined
That does require that the input be an instance of Typeable, but most standard types have a deriving Typeable clause so it's usually not a problem.
You could use a type-class for this:
class ToAny a where
toAny :: a -> Any
instance ToAny Int where
toAny = IsInt
instance ToAny String where
toAny = IsString
For the other case, you could just not call the function on values of other types - it would be less code.

Resources