Elm testing: how to check if a Result is an Err? - decode

I'm writing tests for functions that return a Result. How do I test that it "is" an Err (or an Ok, for that matter) ?
\() -> Expect.equal expectedFailure (Err _)
does not work.
How does one decode a non-parameter?

There may well be a more elegant solution I've missed, but I personally would just write a helper function.
resultOk result =
case result of
Ok _ -> True
Err _ -> False
then in your tests
Expect.true "expected this to be OK" (resultOk <| Ok "All good")
Expect.false "expected this to be an error" (resultOk <| Err "Oh no!")
Expect.true and Expect.false take a string to print if the test fails, and then an expression that should be true (in the case of Expect.true) or false (in the case of Expect.false).

Related

Pattern matching does not call function in F#

open System
[<EntryPoint>]
let main argv =
match argv with
| [| firstArg |] -> printfn "Your first arg is %s", firstArg
| [| |] -> failwith "You didn't pass an argument"
| _ -> failwith "You did something unusual"
0 // return an integer exit code
I wrote this to process the first argument to my F# console application. If I didn't pass an argument it fails with an exception saying "You didn't pass an argument". If I passed at least two arguments, it fails with an exception "You did something unusual". But, when I pass exactly one argument, it tells nothing. Why does not printfn work here?
The reason it didn't print anything here is because you've added an extra comma after the printf. That means the signature is a string -> unit function and string tuple. If you remove the comma then it will work.
A working solution would be
[<EntryPoint>]
let main argv =
match argv with
| [| firstArg |] -> printfn "Your first arg is %s" firstArg
| [| |] -> failwith "You didn't pass an argument"
| _ -> failwith "You did something unusual"
0 // return an integer exit code
You might have seen a compiler warning before running this which said warning FS0020: The result of this expression has type '(string -> unit) * string' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'

Railway oriented programming with Async operations

Previously asked similar question but somehow I'm not finding my way out, attempting again with another example.
The code as a starting point (a bit trimmed) is available at https://ideone.com/zkQcIU.
(it has some issue recognizing Microsoft.FSharp.Core.Result type, not sure why)
Essentially all operations have to be pipelined with the previous function feeding the result to the next one. The operations have to be async and they should return error to the caller in case an exception occurred.
The requirement is to give the caller either result or fault. All functions return a Tuple populated with either Success type Article or Failure with type Error object having descriptive code and message returned from the server.
Will appreciate a working example around my code both for the callee and the caller in an answer.
Callee Code
type Article = {
name: string
}
type Error = {
code: string
message: string
}
let create (article: Article) : Result<Article, Error> =
let request = WebRequest.Create("http://example.com") :?> HttpWebRequest
request.Method <- "GET"
try
use response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
Ok ((new DataContractJsonSerializer(typeof<Article>)).ReadObject(memoryStream) :?> Article)
with
| :? WebException as e ->
use reader = new StreamReader(e.Response.GetResponseStream())
use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
Error ((new DataContractJsonSerializer(typeof<Error>)).ReadObject(memoryStream) :?> Error)
Rest of the chained methods - Same signature and similar bodies. You can actually reuse the body of create for update, upload, and publish to be able to test and compile code.
let update (article: Article) : Result<Article, Error>
// body (same as create, method <- PUT)
let upload (article: Article) : Result<Article, Error>
// body (same as create, method <- PUT)
let publish (article: Article) : Result<Article, Error>
// body (same as create, method < POST)
Caller Code
let chain = create >> Result.bind update >> Result.bind upload >> Result.bind publish
match chain(schemaObject) with
| Ok article -> Debug.WriteLine(article.name)
| Error error -> Debug.WriteLine(error.code + ":" + error.message)
Edit
Based on the answer and matching it with Scott's implementation (https://i.stack.imgur.com/bIxpD.png), to help in comparison and in better understanding.
let bind2 (switchFunction : 'a -> Async<Result<'b, 'c>>) =
fun (asyncTwoTrackInput : Async<Result<'a, 'c>>) -> async {
let! twoTrackInput = asyncTwoTrackInput
match twoTrackInput with
| Ok s -> return! switchFunction s
| Error err -> return Error err
}
Edit 2 Based on F# implementation of bind
let bind3 (binder : 'a -> Async<Result<'b, 'c>>) (asyncResult : Async<Result<'a, 'c>>) = async {
let! result = asyncResult
match result with
| Error e -> return Error e
| Ok x -> return! binder x
}
Take a look at the Suave source code, and specifically the WebPart.bind function. In Suave, a WebPart is a function that takes a context (a "context" is the current request and the response so far) and returns a result of type Async<context option>. The semantics of chaining these together are that if the async returns None, the next step is skipped; if it returns Some value, the next step is called with value as the input. This is pretty much the same semantics as the Result type, so you could almost copy the Suave code and adjust it for Result instead of Option. E.g., something like this:
module AsyncResult
let bind (f : 'a -> Async<Result<'b, 'c>>) (a : Async<Result<'a, 'c>>) : Async<Result<'b, 'c>> = async {
let! r = a
match r with
| Ok value ->
let next : Async<Result<'b, 'c>> = f value
return! next
| Error err -> return (Error err)
}
let compose (f : 'a -> Async<Result<'b, 'e>>) (g : 'b -> Async<Result<'c, 'e>>) : 'a -> Async<Result<'c, 'e>> =
fun x -> bind g (f x)
let (>>=) a f = bind f a
let (>=>) f g = compose f g
Now you can write your chain as follows:
let chain = create >=> update >=> upload >=> publish
let result = chain(schemaObject) |> Async.RunSynchronously
match result with
| Ok article -> Debug.WriteLine(article.name)
| Error error -> Debug.WriteLine(error.code + ":" + error.message)
Caution: I haven't been able to verify this code by running it in F# Interactive, since I don't have any examples of your create/update/etc. functions. It should work, in principle — the types all fit together like Lego building blocks, which is how you can tell that F# code is probably correct — but if I've made a typo that the compiler would have caught, I don't yet know about it. Let me know if that works for you.
Update: In a comment, you asked whether you need to have both the >>= and >=> operators defined, and mentioned that you didn't see them used in the chain code. I defined both because they serve different purposes, just like the |> and >> operators serve different purposes. >>= is like |>: it passes a value into a function. While >=> is like >>: it takes two functions and combines them. If you would write the following in a non-AsyncResult context:
let chain = step1 >> step2 >> step3
Then that translates to:
let asyncResultChain = step1AR >=> step2AR >=> step3AR
Where I'm using the "AR" suffix to indicate versions of those functions that return an Async<Result<whatever>> type. On the other hand, if you had written that in a pass-the-data-through-the-pipeline style:
let result = input |> step1 |> step2 |> step3
Then that would translate to:
let asyncResult = input >>= step1AR >>= step2AR >>= step3AR
So that's why you need both the bind and compose functions, and the operators that correspond to them: so that you can have the equivalent of either the |> or the >> operators for your AsyncResult values.
BTW, the operator "names" that I picked (>>= and >=>), I did not pick randomly. These are the standard operators that are used all over the place for the "bind" and "compose" operations on values like Async, or Result, or AsyncResult. So if you're defining your own, stick with the "standard" operator names and other people reading your code won't be confused.
Update 2: Here's how to read those type signatures:
'a -> Async<Result<'b, 'c>>
This is a function that takes type A, and returns an Async wrapped around a Result. The Result has type B as its success case, and type C as its failure case.
Async<Result<'a, 'c>>
This is a value, not a function. It's an Async wrapped around a Result where type A is the success case, and type C is the failure case.
So the bind function takes two parameters:
a function from A to an async of (either B or C)).
a value that's an async of (either A or C)).
And it returns:
a value that's an async of (either B or C).
Looking at those type signatures, you can already start to get an idea of what the bind function will do. It will take that value that's either A or C, and "unwrap" it. If it's C, it will produce an "either B or C" value that's C (and the function won't need to be called). If it's A, then in order to convert it to an "either B or C" value, it will call the f function (which takes an A).
All this happens within an async context, which adds an extra layer of complexity to the types. It might be easier to grasp all this if you look at the basic version of Result.bind, with no async involved:
let bind (f : 'a -> Result<'b, 'c>) (a : Result<'a, 'c>) =
match a with
| Ok val -> f val
| Error err -> Error err
In this snippet, the type of val is 'a, and the type of err is 'c.
Final update: There was one comment from the chat session that I thought was worth preserving in the answer (since people almost never follow chat links). Developer11 asked,
... if I were to ask you what Result.bind in my example code maps to your approach, can we rewrite it as create >> AsyncResult.bind update? It worked though. Just wondering i liked the short form and as you said they have a standard meaning? (in haskell community?)
My reply was:
Yes. If the >=> operator is properly written, then f >=> g will always be equivalent to f >> bind g. In fact, that's precisely the definition of the compose function, though that might not be immediately obvious to you because compose is written as fun x -> bind g (f x) rather than as f >> bind g. But those two ways of writing the compose function would be exactly equivalent. It would probably be very instructive for you to sit down with a piece of paper and draw out the function "shapes" (inputs & outputs) of both ways of writing compose.
Why do you want to use Railway Oriented Programming here? If you just want to run a sequence of operations and return information about the first exception that occurs, then F# already provides a language support for this using exceptions. You do not need Railway Oriented Programming for this. Just define your Error as an exception:
exception Error of code:string * message:string
Modify the code to throw the exception (also note that your create function takes article but does not use it, so I deleted that):
let create () = async {
let ds = new DataContractJsonSerializer(typeof<Error>)
let request = WebRequest.Create("http://example.com") :?> HttpWebRequest
request.Method <- "GET"
try
use response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
return ds.ReadObject(memoryStream) :?> Article
with
| :? WebException as e ->
use reader = new StreamReader(e.Response.GetResponseStream())
use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
return raise (Error (ds.ReadObject(memoryStream) :?> Error)) }
And then you can compose functions just by sequencing them in async block using let! and add exception handling:
let main () = async {
try
let! created = create ()
let! updated = update created
let! uploaded = upload updated
Debug.WriteLine(uploaded.name)
with Error(code, message) ->
Debug.WriteLine(code + ":" + message) }
If you wanted more sophisticated exception handling, then Railway Oriented Programming might be useful and there is certainly a way of integrating it with async, but if you just want to do what you described in your question, then you can do that much more easily with just standard F#.

Writing the function "once" in Elixir

I'm coming to Elixir from primarily a Javascript background. in JS, it's possible to write a higher order function "once" which returns a function that will invoke the passed in function only once, and returns the previous result on subsequent calls- the trick is manipulating variables that were captured via closure:
var once = (func) => {
var wasCalled = false, prevResult;
return (...args) => {
if (wasCalled) return prevResult;
wasCalled = true;
return prevResult = func(...args);
}
}
It seems to me that it's not possible to create this function in Elixir, due to its different variable rebinding behavior. Is there some other clever way to do it via pattern matching or recursion, or is it just not possible? Without macros that is, I'd imagine those might enable it. Thanks
Using the current process dictionary:
defmodule A do
def once(f) do
key = make_ref()
fn ->
case Process.get(key) do
{^key, val} -> val
nil ->
val = f.()
Process.put(key, {key, val})
val
end
end
end
end
Or if the function will be passed across processes, an ets table can be used:
# ... during application initialization
:ets.new(:cache, [:set, :public, :named_table])
defmodule A do
def once(f) do
key = make_ref()
fn ->
case :ets.lookup(:cache, key) do
[{^key, val}] -> val
[] ->
val = f.()
:ets.insert(:cache, {key, val})
val
end
end
end
end
Application.put_env / Application.get_env can also be used to hold global state, though usually is used for configuration settings.
It's not considered idiomatic in most cases, but you can do this with Agent:
defmodule A do
def once(fun) do
{:ok, agent} = Agent.start_link(fn -> nil end)
fn args ->
case Agent.get(agent, & &1) do
nil ->
result = apply(fun, args)
:ok = Agent.update(agent, fn _ -> {:ok, result} end)
result
{:ok, result} ->
result
end
end
end
end
Now if you run this:
once = A.once(fn sleep ->
:timer.sleep(sleep)
1 + 1
end)
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
You'll see that the first line is printed after 1 second, but the next 3 are printed instantly, because the result is fetched from the agent.
While both already given answers are perfectly valid, the most precise translation from your javascript is shown below:
defmodule M do
use GenServer
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_args) do
Process.sleep(1_000)
{:ok, 42}
end
def value() do
start_link()
GenServer.call(__MODULE__, :value)
end
def handle_call(:value, _from, state) do
{:reply, state, state}
end
end
(1..5) |> Enum.each(&IO.inspect(M.value(), label: to_string(&1)))
Use the same metric as in #Dogbert’s answer: the first value is printed with a delay, all subsequent are printed immediately.
This is an exact analog of your memoized function using GenServer stage. GenServer.start_link/3 returns one of the following:
{:ok, #PID<0.80.0>}
{:error, {:already_started, #PID<0.80.0>}}
That said, it is not restarted if it’s already started. I do not bother to check the returned value since we are all set in any case: if it’s the initial start, we call the heavy function, if we were already started, the vaklue is already at fingers in the state.

How to Dict.get a case insensitive key?

I'd like to grab the Total-Records key of a response.headers HTTP response.
Problem is that in some browser it is as returned by the server Total-Records but in some other, it is in lower case.
I'd like to get the value of the Total-Records header regardless of its case.
How would you do that?
Yet another alternative is to use the find function from elm-community/dict-extra to provide a custom comparison operator:
import Dict.Extra
caseInsensitiveGet : String -> Dict String v -> Maybe v
caseInsensitiveGet key =
let
lowerKey = String.toLower key
in
Dict.Extra.find (\k _ -> String.toLower k == lowerKey)
>> Maybe.map Tuple.second
In the absence of a general-purpose case-insensitive dictionary, you can hack together a manual lookup:
caseInsensitiveGet : String -> Dict String v -> Maybe v
caseInsensitiveGet key dict =
let
lowerKey = String.toLower key
in
Dict.toList dict
|> List.filterMap (\(k, v) ->
if String.toLower k == lowerKey then
Just v
else
Nothing)
|> List.head
Note that this will perform worse the larger the dictionary is. In this form it is possible to have multiple variations of the same text with different cases, so it isn't perfect, but if you're just looking for a header, it should suffice.
I think the least costly way - in general - is simply to do the two look ups and see what you get. For example,
case (Dict.get "Total-Records" response.headers, Dict.get "total-Records" response.headers) of
(Just s, _) ->
s
(_, Just s) ->
s
_ ->
<handle error case>
Alternatively you could replace the above with if then else.
In this situation I think I might go (uses elm-community/list-extra):
getFirstCaseInsensitive : String -> Dict String v -> Maybe v
getFirstCaseInsensitive key dict =
let
key_ =
String.toLower key
in
dict
|> Dict.toList
|> List.Extra.find
((==) key_ << String.toLower << Tuple.first)
|> Maybe.map Tuple.second
Thank you all for your answers, I ended up using Dict.Extra.mapKeys:
import Dict.Extra
headers =
Dict.Extra.mapKeys String.toLower response.headers

Haskell - error in download code

downloadCSVFile ::String-> IO (Bool,String)
downloadCSVFile company_code = do
let a="http://ichart.finance.yahoo.com/table.csv?s=" ++ company_code
let b=simpleHTTP $ getRequest a
src <- ( b >>= getResponseBody)
rcode <- fmap rspCode <$> b
h <- fmap findHeader HdrLocation b
case rcode of
Left err -> return (False, "Connection error: " ++ show err)
Right (2,_,_) -> return (True,src)
Right (4,_,_) -> return (False,"Invalid URL/The requested page does not exist..")
Right (5,_,_) -> return (False, "Internal error in the server on trying to process the request")
Right (3,_,_) ->
case h of
Nothing -> return (False, "Error : " )
Just url -> downloadCSVFile a
Please help me to resolve the following error and help me to check whether I've included all the condition in the "case" statement or not:
You've got several problems in your code. The first is your return type. You're trying to encode the notion of failure or success using a tuple and a string. Instead, you could use the Either type to handle this much more elegantly
downloadCSVFile :: String -> IO (Either String String)
downloadCSVFile company_code = do
let url = "http://ichart.finance.yahoo.com/table.csv?s=" ++ company_code
Next, you use let b = simpleHTTP $ getRequest a. You're assigning an IO action inside an IO function, when instead you should be extracting the result using <-
response <- simpleHTTP $ getRequest url
This lets you write the next few lines without duplicate fmaps (<$> is the infix form of fmap, so you're fmap-ing multiple times unnecessarily)
src <- getResponseBody response
let rcode = fmap rspCode response
header = fmap findHeader HdrLocation response
And now we come across what seems to be the culprit. Your use of fmap findHeader HdrLocation response is incorrect. What you meant was fmap (findHeader HdrLocation) response, the parentheses are very important here.
Since we're now using the Either type, we have to change our case statement a bit, but it's certainly cleaner now. We use the convention Left for errors and Right for success. This is exactly how the Network.HTTP library works with the Result type.
case rcode of
Left err -> return $ Left $ "Connection error: " ++ show err
Right (2, _, _) -> return $ Right src
Right (4, _, _) -> return $ Left "Invalid URL..."
Right (5, _, _) -> return $ Left "Internal error in the server..."
Right (3, _, _) ->
case header of
Nothing -> return $ Left "Error"
Just url' -> downloadCSVFile $ fromJust $ parseURI url
To sum up, the real problem was with the line
h <- fmap findHeader HdrLocation <$> b
for its lack of parentheses that would have made it correct. We also looked into using do notation to our advantage to avoid superfluous fmaps, and also assuring the correct behavior of the program. By defining b = simpleHTTP $ getRequest a, you were assigning b to that action, but not to it's result. Depending on the compiler or platform, that could mean that every time you used b, it could be trying to download that URL again. That is obviously bad, since any one of them could fail, it eats up bandwidth, and hits the yahoo server harder than need be. Finally, we examined how we can use the Either data type for more elegant error handling. It's certainly possible that you might want to add another case to case rcode of in which you accidentally return (True, "Some error message") instead of (False, "Some error message"), in which case you could crash your program! By delimiting ourselves with Left and Right, we remove another point of failure.

Resources