Yesod custom field of type [Double] - json

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"

Related

Unable to define a parser in Haskell: Not in scope: type variable ‘a’

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)]

How to pass only one side of either as a parameter Haskell

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.

How to partially apply a function with desired order in Elm?

Suppose I have a function that takes 3 parameters as input. How to partially apply this function in Elm so it takes first and last parameters and waits for the second parameter to return the final result?
This can be done in Ramda with R.__ which is named placeholer.
You can just wrap it in a lambda function that has the shape you want, which is what would be produced by any other means anyway:
\y -> f "x" y "z"
In a curried language I find the need to do this so rare that adding syntax sugar specifically for this use case seems unnecessary.
As glennsl says, you can wrap your function in another function with the argument order that you want. his answer assumes that you know statically what the first and third arguments are, if you don't, but just want to partially apply the first and third argument, then apply the second you can take a function like,
joinThree : String -> String -> String -> String
joinThree first second third =
first ++ second ++ third
and wrap it in a new function that calls the first function, but with a different argument order,
joinThreeWrapper : String -> String -> String -> String
joinThreeWrapper first third second =
joinThree first second third
This allows you to call this function like,
welcomeToNeverland : String -> String
welcomeToNeverland name =
let
myGreeting = joinThreeWrapper "Welcome " " to Neverland"
in
myGreeting name
Then you can use it like,
text (welcomeToNeverland "Wendy")
-- Welcome Wendy to Neverland
Writing joinThreeWrapper like this makes it a bit easier to map your function over a list like,
greetMany : List String -> List String
greetMany names =
List.map (joinThreeWrapper "Welcome " ", this is our town. ") names
so that you can do,
text (List.map (++) (greetMany ["Jesse", "Carl"]))
-- Welcome Jesse, this is our town. Welcome Carl, this is our town.
You can use flip from the core Basics module.
For instance:
> append3 x y z = x ++ y ++ z
<function> : appendable -> appendable -> appendable -> appendable
> hello = flip (append3 "Hello, ") "!"
<function> : String -> String
> hello "world"
"Hello, world!" : String

How to read value of property depending on an argument

How can I get the value of a property given a string argument.
I have a Object CsvProvider.Row which has attributes a,b,c.
I want to get the attribute value depending on property given as a string argument.
I tried something like this:
let getValue (tuple, name: string) =
snd tuple |> Seq.averageBy (fun (y: CsvProvider<"s.csv">.Row) -> y.```name```)
but it gives me the following error:
Unexpected reserved keyword in lambda expression. Expected incomplete
structured construct at or before this point or other token.
Simple invocation of function should look like this:
getValue(tuple, "a")
and it should be equivalent to the following function:
let getValue (tuple) =
snd tuple |> Seq.averageBy (fun (y: CsvProvider<"s.csv">.Row) -> y.a)
Is something like this is even possible?
Thanks for any help!
The CSV type provider is great if you are accessing data by column names statically, because you get nice auto-completion with type inference and checking.
However, for a dynamic access, it might be easier to use the underlying CsvFile (also a part of F# Data) directly, rather than using the type provider:
// Read the given file
let file = CsvFile.Load("c:/test.csv")
// Look at the parsed headers and find the index of column "A"
let aIdx = file.Headers.Value |> Seq.findIndex (fun k -> k = "A")
// Iterate over rows and print A values
for r in file.Rows do
printfn "%A" (r.Item(aIdx))
The only unfortunate thing is that the items are accessed by index, so you need to build some lookup table if you want to easily access them by their name.

Persistent: Convert Text to Key

I'm using persistent and persistent-mysql. I have a Monad SqlM
type SqlM a = SqlPersist (ResourceT IO) a)
Inside my function
testFun :: T.Text -> SqlM ()
testFun someId = ...
I can query the Database by using
entity <- selectFirst [SomeField ==. someId]
But I would like to select entitys by ID. I have to convert/pack someId to the Key - Type. I know this isn't the way to do it, but i tried:
entity <- get $ Key { unKey = PersistInt64 (read $ T.unpack someId) }
this fails with:
Couldn't match type `PersistEntityBackend
(Entity (DBTableGeneric backend0))'
with `Database.Persist.GenericSql.Raw.SqlBackend'
The type variable `backend0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: Key (Entity (DBTableGeneric backend0))
Actual type: KeyBackend
Database.Persist.GenericSql.Raw.SqlBackend
(Entity (DBTableGeneric backend0))
In the second argument of `($)', namely
`Key {unKey = PersistInt64 (read $ T.unpack someId)}'
Any ideas what's going wrong?
I usually use fromPathPiece for this kind of conversion. As for your error message, you can probably just add a type signature to clarify to the compiler what types you're working with.