Using Either recursively - haskell

So I have defined a function like this one below:
myFunction :: String -> Either String MyType
I am reading String until the end. Left is used for handling errors. Right suppose to return me the tuple. In myFunction I am calling anotherFunction and checking if it returns Left or Right like this:
myFunction :: String -> Either String MyType
myFunction "" = Right -- want to return MyType here
myFunction s =
case anotherFunction s of
Left c -> Left c
Right (v1, v2, t) -> -- want to call myFunction again with t
When anotherFunction returns Right, I want to call myFunction again recursively without loosing v1 and v2. How can I achieve that with recursion?
Here is the exact definition of MyType:
data MyType = MyString String | MyInt Int | MyMap [(String, MyType)] deriving (Show, Eq)

Related

How can I declare the types for this problem?

I'm trying to create a simple programming language with some primitives and user defined functions.
These are the types I created:
data Type = IntT | BoolT
data Value = IntV Int | BoolV Bool | OperatorCall String [Value]
data Expr = LetE String Value | ProcedureCall String [Value]
As you can see, I've divided functions into operators (which return a value) and procedures (which don't return anything and act as expressions instead of values). A function call contains the string id of the function being called and the list of arguments being passed. Also, a program is just a list of expressions (I've omitted user defined functions here for the sake of simplicity)
My problem comes from the fact that I need to write a function that parses a function call from a string:
parseFunctionCall :: String -> ???
...
The return type of that function can be a Value (for operator calls) or an Expr (for procedure calls). This function is rather complicated and I'd prefer to avoid writing it twice, or polluting it with an Either return type. What should I do? How can I change my types so that this can be achieved cleanly? Something like this perhaps, but I don't think this is the way:
type FunctionCall = (String, [Value])
data Value = ... | OperatorCall FunctionCall
data Expr = ... | ProcedureCall FunctionCall
parseAsFunctionCall :: String -> FunctionCall
...
You can have the function call parser return (String, [Value]), and let the caller fix that up into whatever data structure they like best -- in your case, by applying \(s, vs) -> OperatorCall s vs if parsing a value or \(s, vs) -> ProcedureCall s vs if parsing an expression.
parseFunctionCall :: Parser (String, [Value])
parseLiteralInt :: Parser Int
parseLiteralBool :: Parser Bool
parseLet :: Parser (String, Value)
(parseFunctionCall, parseLiteralInt, parseBool, parseLet) = {- ... -}
parseValue :: Parser Value
parseValue =
((\(s, vs) -> OperatorCall s vs) <$> parseFunctionCall)
<|>
(IntV <$> parseLiteralInt)
<|>
(BoolV <$> parseLiteralBool)
parseExpr :: Parser Expr
((\(s, vs) -> ProcedureCall s vs) <$> parseFunctionCall)
<|>
((\(s, v) -> Let s v) <$> parseLet)

How to create a newtype of parser?

newtype Parser a = PsrOf{
-- | Function from input string to:
--
-- * Nothing, if failure (syntax error);
-- * Just (unconsumed input, answer), if success.
dePsr :: String -> Maybe (String, a)}
I want to create a newtype of Parser to see how it looks like.
I tried
*ParserLib> PsrOf{"hello"}
But it comes up with an error
<interactive>:5:7: error: parse error on input ‘"’
You've already created the type. Now you want to create a value of that type. To do that, you need to call PsrOf with a value of type String -> Maybe (String, a). For example:
newtype Parser a = PsrOf { dePsr :: String -> Maybe (String, a) }
get3 :: String -> Maybe (String, Int)
get3 ('3':xs) = Just (xs, 3)
get3 _ = Nothing -- Any string, including the empty string, that doesn't start with '3'
get3P :: Parser Int
get3P = PsrOf get3
To actually use the parser, you need to extract the function before applying it to a string:
dePsr get3P "38" -- Just ("8", 3)
dePsr get3P "" -- Nothing
dePsr get3P "hello" -- Nothing
Record syntax here is just used to simplify the definition of the type, instead of writing
newtype Parser a = PsrOf (String -> Maybe (String, a))
dePsr :: Parser a -> String -> Maybe (String, a)
dPsr (PsrOf f) = f
The rest of the uses for record syntax (pattern matching or making slightly modified copies of a value) don't really apply usefully to types that wrap a single value.

How to ignore a polymorph readable type, while reading?

I have a problem similar to:
data Foo a = Foo { myInt :: Integer, myValue :: a } deriving Read
bar :: String -> Integer
bar = myInt . read
main = print $ bar stringWithFooOfa
i don't want to use something like read . (!!1) . words, if i don't need to.
Add a type annotation to read. As commenters suggested, Haskell has no way of knowing what you're trying to read since you immediately turn it into an Int. To be more clear, consider this example:
data Foo a = Foo { myInt :: Integer, myValue :: a } deriving Read
data Foo2 a = Foo { myInt2 :: Integer } deriving Read
bar :: String -> Integer
bar = myInt . read
Now there are two very different behaviors for bar possible and it's hard to know which is correct.
To tell Haskell which one you want, use an inline annotation around read:
bar :: String -> Integer
bar = myInt . (read :: String -> Foo ())
Notice that I pick an a, too. Otherwise, we'll be in the same boat as above but just with a instead of Foo.

Type synonym for Haskell giving type errors

I am attempting to create a type synonym that looks something like this:
data Result = Either String [Token]
I'm having difficulty because while this code compiles, when I attempt to create a Result with a [Token], haskell complains
Not in scope: data constructor `Result'
How can I define a type synonym with a constructor that works?!
How are you trying to create a Result??
The correct way is:
If you declare it as a data:
data Result = Result (Either String [Token])
f :: Result
f = (Result (Left "test"))
Or, if you declare as a type:
type Result = Either String [Token]
f :: Result
f = Left "test"
With
type Result = Either String Token
the data constructors are
Left :: String -> Result
Right :: [Token] -> Result
because
data Either a b = Left a | Right b
With
data Result = Either String [Token]
you declare Result to have one two-argument constructor, Either with type
Either :: String -> [Token] -> Result
which is a) probably not what you want and b) confusing, because Either is a well-known type constructor.
I think you need to use type and not data
type Result = Either String [Token]

Haskell abstract datatypes and retrieving characters/defining as strings

I had a datatype, example:
data MyData = Something1 String
and then I had a function
myFunction :: MyData -> String
myFunction x = x
within myFunction I want to refer to the characters ie ['S','o','m','e'......'1'] which are in my data type MyData. However, I get the following error:
Couldn't match expected type [Char]'
with actual typeMyData'
Expected type: String
Actual type: MyData
As far as I understand [Char] is the same as String, and I have declared 'Something1' as String, so it should work?
[Char] is the same as String, but neither is the same as MyData. To access the string stored within your data type, you'll need to use pattern matching:
myFunction :: MyData -> String
myFunction (Something1 xs) = xs
This is because the data keyword makes a completely new data type. If you only wanted an alias, you could also use the type keyword:
type MyData = String
myFunction :: MyData -> String
myFunction x = x
MyData is not the same as String. It is just very similar.
You can declare a type synonym like this:
type MyData = String
and then MyData and String are two names for the same type. In fact, String is already a type synonym of [Char]. In this case, myFunction is just the identity function id.
Or you can use pattern matching to extract the String from a MyData like this:
myFunction :: MyData -> String
myFunction (Something1 xs) = xs
Alternatively, you can use the record syntax to make the accessor automatically:
data MyData = Something1 { myFunction :: String}
(this is practically identical to declaring myFunction as above, except you can now construct MyDatas using the syntax Something1 { myFunction = x } as well as Something1 x)

Resources