One of my functions returns either:
parse :: Int -> String -> Either String JsonLikeValue
And other takes JsonLikeValue as a parameter:
convert :: Int -> JsonLikeValue -> Either InvalidState To
JsonLikeValue is custom data type:
data JsonLikeValue = JLString String | JLInt Int | JLArray [JsonLikeValue] deriving (Show, Eq)
And when I call:
convert num (parse size message)
it gives following:
Couldn't match expected type ‘JsonLikeValue’
with actual type ‘Either String JsonLikeValue’
How can this be avoided and only right side be passed as argument?
Thanks in advance :)
EDIT: solution marked as answer is very helpful since it takes into consideration all possible outcomes, and as I'm not an expert but still, looks more professional, so it is very important to take a look at it.
But what was enough to solve the required extraction was:
extractValue :: Either String JsonLikeValue -> JsonLikeValue
extractValue a = case a of
Left e -> JLArray []
Right r -> r
where in case of Right it returns only value, and in case of Left it returns something of required data type. Note that this only works if you're 100% sure that argument will return Right value. Otherwise, check answer below.
Another good notice in comments is to use fromRight from Data.Either
The first problem is that we need to return something in case the parse value returns a Left … value. We can for example make a function that combines the two "errors" with:
myfunction :: Int -> Int -> String -> Either (Either String InvalidState) To
myfunction = …
We can make use of pattern matching to unpack the value in case of a Right and then use the convert function, like:
myfunction :: Int -> Int -> String -> Either (Either String InvalidState) To
myfunction size num message = go (parse size message)
where go (Left e) = Left (Left e)
go (Right jlv) = pp (convert num jlv)
pp (Left e) = Left (Right e)
pp (Right r) = Right r
Here go thus inspects the result of the parse size message value, and in case it is a Left e, we return Left (Left e). If it is a Right jlv (with jlv the JsonLikeValue wrapped in it), we thus call convert num jlv.
We still need to post-process the result with the pp function. The convert num jlv will have type Either InvalidState To, and we need to convert it to an Either (Either String InvalidState) To. We do that by converting a Left e to a Left (Right e), and a Right r to a Right r. Note that the Right in the body is a data constructor of the Either (Either String InvalidState) To type, wheras the Right in the head is a data constructor of the Either InvalidState To, so the two are not the same.
Related
I am trying to define a parser in Haskell. I am a total beginner and somehow didn't manage to find any solution to my problem at all.
For the first steps I tried to follow the instructions on the slides of a powerpoint presentation. But I constantly get the error "Not in scope: type variable ‘a’":
type Parser b = a -> [(b,a)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x:xs)]
error: Not in scope: type variable ‘a’
|
11 | type Parser b = a -> [(b,a)]
| ^
I don't understand the error but moreover I don't understand the first line of the code as well:
type Parser b = a -> [(b,a)]
What is this supposed to do? On the slide it just tells me that in Haskell, Parsers can be defined as functions. But that doesn't look like a function definition to me. What is "type" doing here? If it s used to specify the type, why not use "::" like in second line above? And "Parser" seems to be a data type (because we can use it in the type definition of "item"). But that doesn't make sense either.
The line derives from:
type Parser = String -> (String, Tree)
The line I used in my code snippet above is supposed to be a generalization of that.
Your help would be much appreciated. And please bear in mind that I hardly know anything about Haskell, when you write an answer :D
There is a significant difference between the type alias type T = SomeType and the type annotation t :: SomeType.
type T = Int simply states that T is just another name for the type Int. From now on, every time we use T, it will be replaced with Int by the compiler.
By contrast, t :: Int indicates that t is some value of type Int. The exact value is to be specified by an equation like t = 42.
These two concepts are very different. On one hand we have equations like T = Int and t = 42, and we can replace either side with the other side, replacing type with types and values with values. On the other hand, the annotation t :: Int states that a value has a given type, not that the value and the type are the same thing (which is nonsensical: 42 and Int have a completely different nature, a value and a type).
type Parser = String -> (String, Tree)
This correctly defines a type alias. We can make it parametric by adding a parameter:
type Parser a = String -> (String, a)
In doing so, we can not use variables in the right hand side that are not parameters, for the same reason we can not allow code like
f x = x + y -- error: y is not in scope
Hence you need to use the above Parser type, or some variation like
type Parser a = String -> [(String, a)]
By contrast, writing
type Parser a = b -> [(b, a)] -- error
would use an undeclared type b, and is an error. At best, we could have
type Parser a b = b -> [(b, a)]
which compiles. I wonder, though, is you really need to make the String type even more general than it is.
So, going back to the previous case, a possible way to make your code run is:
type Parser a = String -> [(a, String)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
Note how [(x, xs)] is indeed of type [(Char, String)], as needed.
If you really want to generalize String as well, you need to write:
type Parser a b = b -> [(b, a)]
item :: Parser Char String
item = \inp -> case inp of
[] -> []
(x:xs) -> [(xs, x)]
we are currently sitting on a task from university, which we don't fully understand (please no solution but only ideas or suggestions).
What is given is a type:
type MyType = String -> String
Now we are trying to be able to have a function, which takes 2 Strings and a function (the type) and then gives a function (type)
myCode :: String -> String -> MyType -> MyType
and we already implemented a function, which can be used as MyType one:
emptyString :: MyType
emptyString :: (\a -> "")
The task is to be able to store several 2x Strings. This is our current idea:
myCode :: String -> String -> MyType ->MyType
myCode a b c = (\x -> b)
in this case we have an input String, which is "Hello" and another one which is "World" and then as c we put in the "emptyString".
This works for one String, because when we type the following in the console:
a = (myCode "Hello" "World" emptyString) ""
we get "World" on input "a". Now the hard part: We should be able to store several of these (searching them is another task, not needed right now). We thought we might be able to use "a" now when declaring another variable:
b = (myCode "1" "2" a) "Hello" "World" emptyString "")
This would call in "b" the function saved as "a" and within this the "emptyString".
As you may have guessed - it doesn't work! And we are really at a loss on how to carry on from now.
When you reached this part, it means you took the time to understand our complicated explanation of our task - thanks a lot.
Thanks for suggestions and help in advance!
From the question linked by amalloy in the comments, it looks like you are trying to build a phonebook based on a continuation passing style like paradigm.
Basically, what is supposed to happen for your type
myCode :: String -> String -> MyType -> MyType
is that you will generate a piece of data dat = myCode a b pb, which is of type MyType. So, you can query dat with an s :: String and it will output another String. In the operation of dat s, if you expand it to the definition,
dat s = myCode a b pb s
you have access to three strings, a, b, and whatever pb s returns. You will build up functionality recursively, either by doing something with a b and s, or pushing it down the road to pb, letting the continuation handle it.
Hope this helps without giving too much away.
I want to create a custom field in Yesod that is a text field with a JSON array of doubles. However I keep getting type errors. My current attempt is:
doubleListField :: RenderMessage master FormMessage => Field sub master [Double]
doubleListField = Field
{ fieldParse = parseHelper $ Right . decodeUtf8 . parse json
, fieldView = \theId name attrs val isReq -> toWidget [hamlet|
$newline never
<input id="#{theId}" name="#{name}" *{attrs} type="number" :isReq:required="" value="Hey">
|]
}
(Correct whitespace found: https://gist.github.com/4394850)
I'm currently failing with:
Couldn't match expected type `Data.ByteString.Internal.ByteString'
with actual type `[Text]
-> m0 (Either (SomeMessage master0) (Maybe Text))'
In the second argument of `($)', namely `parseHelper $ Right'
In the `fieldParse' field of a record
In the expression:
Field
{fieldParse = parse json $ parseHelper $ Right,
fieldView = \ theId name attrs val isReq
-> toWidget (\ _render_a5Cg -> ...)}
fieldView I'll modify and I know how to go about that but I'm flummoxed about how fieldParse should look. Thanks!
Please note that your code does not match the error.
The fieldParse function should turn the user submitted data into a Haskell structure. As you discovered, there is a parseHelper function that simplifies creating the field.
The type of parseHelper is essentially (Text -> Either FormMessage a) -> X, where X is the exact type of fieldParse. That is, once you pass one argument to the helper, you get a correct fieldParse.
The argument to parseHelper should be a function, that recieves a Text input and returns Right [Double] or Left FormMessage if parsing failed.
Depending on what you use to parse the JSON, the function could look like this (assuming existence of a few more helpers that you will most likely have to write):
fieldParse = parseHelper $ \text -> case parse json text of
Right value | isListOfDoubles value -> Right $ extractListOfDoubles value
_ -> Left "Wrong input"
If I want to add a space at the end of a character to return a list, how would I accomplish this with partial application if I am passing no arguments?
Also would the type be?
space :: Char -> [Char]
I'm having trouble adding a space at the end due to a 'parse error' by using the ++ and the : operators.
What I have so far is:
space :: Char -> [Char]
space = ++ ' '
Any help would be much appreciated! Thanks
Doing what you want is so common in Haskell it's got its own syntax, but being Haskell, it's extraordinarily lightweight. For example, this works:
space :: Char -> [Char]
space = (:" ")
so you weren't far off a correct solution. ([Char] is the same as String. " " is the string containing the character ' '.) Let's look at using a similar function first to get the hang of it. There's a function in a library called equalFilePath :: FilePath -> FilePath -> Bool, which is used to test whether two filenames or folder names represent the same thing. (This solves the problem that on unix, mydir isn't the same as MyDir, but on Windows it is.) Perhaps I want to check a list to see if it's got the file I want:
isMyBestFile :: FilePath -> Bool
isMyBestFile fp = equalFilePath "MyBestFile.txt" fp
but since functions gobble their first argument first, then return a new function to gobble the next, etc, I can write that shorter as
isMyBestFile = equalFilePath "MyBestFile.txt"
This works because equalFilePath "MyBestFile.txt" is itself a function that takes one argument: it's type is FilePath -> Bool. This is partial application, and it's super-useful. Maybe I don't want to bother writing a seperate isMyBestFile function, but want to check whether any of my list has it:
hasMyBestFile :: [FilePath] -> Bool
hasMyBestFile fps = any (equalFilePath "MyBestFile.txt") fps
or just the partially applied version again:
hasMyBestFile = any (equalFilePath "MyBestFile.txt")
Notice how I need to put brackets round equalFilePath "MyBestFile.txt", because if I wrote any equalFilePath "MyBestFile.txt", then filter would try and use just equalFilePath without the "MyBestFile.txt", because functions gobble their first argument first. any :: (a -> Bool) -> [a] -> Bool
Now some functions are infix operators - taking their arguments from before and after, like == or <. In Haskell these are just regular functions, not hard-wired into the compiler (but have precedence and associativity rules specified). What if I was a unix user who never heard of equalFilePath and didn't care about the portability problem it solves, then I would probably want to do
hasMyBestFile = any ("MyBestFile.txt" ==)
and it would work, just the same, because == is a regular function. When you do that with an operator function, it's called an operator section.
It can work at the front or the back:
hasMyBestFile = any (== "MyBestFile.txt")
and you can do it with any operator you like:
hassmalls = any (< 5)
and a handy operator for lists is :. : takes an element on the left and a list on the right, making a new list of the two after each other, so 'Y':"es" gives you "Yes". (Secretly, "Yes" is actually just shorthand for 'Y':'e':'s':[] because : is a constructor/elemental-combiner-of-values, but that's not relevant here.) Using : we can define
space c = c:" "
and we can get rid of the c as usual
space = (:" ")
which hopefully make more sense to you now.
What you want here is an operator section. For that, you'll need to surround the application with parentheses, i.e.
space = (: " ")
which is syntactic sugar for
space = (\x -> x : " ")
(++) won't work here because it expects a string as the first argument, compare:
(:) :: a -> [a] -> [a]
(++) :: [a] -> [a] -> [a]
My current project involves lexing and parsing script code, and as such I'm using fslex and fsyacc. Fslex LexBuffers can come in either LexBuffer<char> and LexBuffer<byte> varieties, and I'd like to have the option to use both.
In order to user both, I need a lexeme function of type ^buf -> string. Thus far, my attempts at specialization have looked like:
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: char array) =
new System.String(lexbuf.Lexeme)
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: byte array) =
System.Text.Encoding.UTF8.GetString(lexbuf.Lexeme)
I'm getting a type error stating that the function body should be of type ^buf -> string, but the inferred type is just string. Clearly, I'm doing something (majorly?) wrong.
Is what I'm attempting even possible in F#? If so, can someone point me to the proper path?
Thanks!
Functions and members marked as inline cannot be overloaded, so your original strategy won't work. You need to write different code for both of the declarations, so you need to use overloading (if you want to write this without boxing and dynamic type tests).
If you're using standard F# tools, then the type you'll get as a buffer will always be LexBuffer<'T> and you want to have two overloads based on the type argument. In this case, you don't need the static member constraints at all and can write just:
type Utils =
static member lexeme(buf:LexBuffer<char>) =
new System.String(buf.Lexeme)
static member lexeme(buf:LexBuffer<byte>) =
System.Text.Encoding.UTF8.GetString(buf.Lexeme)
Are you sure this strategy of redefining inline functions with different argument types can work? Looks like you're trying to overload to me...
type LexBuffer<'a>(data : 'a []) =
member this.Lexeme = data
let lexeme (buf : LexBuffer<'a>) =
match box buf.Lexeme with
| :? (char array) as chArr ->
new System.String(chArr)
| :? (byte array) as byArr ->
System.Text.Encoding.UTF8.GetString(byArr)
| _ -> invalidArg "buf" "must be either char or byte LexBuffer"
new LexBuffer<byte>([| 97uy; 98uy; 99uy |])
|> lexeme
|> printfn "%A"
new LexBuffer<char>([| 'a'; 'b'; 'c' |])
|> lexeme
|> printfn "%A"