How to get the first Some of an HList when composing Spray directives (Shapeless, Scala) - spray

Let's say that I want to create a simple directive to fetch a session identifier off the HTTP request but with a twist: The request might be using an old format but either should be considered valid for the moment because of backwards compatibility.
I sketched out something simple that basically composes two existing directives together with the resulting directive being a...
Directive[Option[String] :: Option[String] :: HNil]
Here's the meat of my question: Are there any concise ways that to basically say "given a Directive that is an HList of multiple Option's, get the first Some and use that otherwise use a default value"?
My current implementation. Works but seems a bit messy and isn't re-usable at all.
def sessionIdentifier: Directive1[String] = {
(optionalHeaderValueByName("New-Session-Header") & parameter("oldsessionparam"?)).hmap {
case Some(x) :: _ :: HNil if x.nonEmpty => x
case _ :: Some(x) :: HNil if x.nonEmpty => x
case _ => getNewSessionId()
}
}

If all the element types are guaranteed to be of type Option[String] then the following will be a little terser,
# import shapeless._
import shapeless._
# val opts = Option.empty[String] :: Option("foo") :: Option("bar") :: HNil
opts: Option[String] :: Option[String] :: Option[String] :: HNil = ...
# opts.toList.flatten.headOption.getOrElse("default")
res0: String = "foo"

Your implementation is quite good actually. It may be refactored as
val sessionParameters =
optionalHeaderValueByName("New-Session-Header") & parameter("oldsessionparam".?)
val sessionIdentifier =
sessionParameters.hmap {
case newId :: oldId :: HNil =>
newId.filter(_.nonEmpty)
.orElse(oldId.filter(_.nonEmpty))
.getOrElse(getNewSessionId())
}

Related

What is missing using interfaces compared to true type-classes?

F# does not (currently) support type-classes. However, F# does support the OOP aspects of C#.
I was wondering, what is lost doing this approach compared to true type-classes?
// A concrete type
type Foo =
{
Foo : int
}
// "Trait" for things that can be shown
type IShowable =
abstract member Show : unit -> string
module Showable =
let show (showable : IShowable) =
showable.Show()
// "Witness" of IShowable for Foo
module Foo =
let asShowable (foo : Foo) =
{
new IShowable with
member this.Show() = string foo.Foo
}
// Slightly awkward usage
{ Foo = 123 }
|> Foo.asShowable
|> Showable.show
|> printfn "%s"
Your suggestion works for simple typeclasses that operate on a single value of a type, like Show. However, what happens when you need a typeclass that isn't so object-oriented? For example, when we want to add two numbers, neither one corresponds to OO's this object:
// not real F#
typeclass Numeric<'a> = // e.g. Numeric<int> or Numeric<float>
abstract member (+) : 'a -> 'a -> 'a // e.g. 2 + 3 = 5 or 2.0 + 3.0 = 5.0
...
Also, keep in mind that many useful typeclasses require higher-kinded types. For example, consider the monad typeclass, which would look something like this:
// not real F#
typeclass Monad<'m<_>> = // e.g. Monad<Option<_>> or Monad<Async<_>>
abstract member Return<'a> : 'a -> 'm<'a>
abstract member Bind<'a, 'b> : 'm<'a> -> ('a -> 'm<'b>) -> 'm<'b>
There's no good way to do this with .NET interfaces.
Higher-kinded type classes are indeed impossible to model with interfaces, but that's just because F# does not support higher-kindedness, not because of type classes themselves.
The deeper thing to note is that your encoding isn't actually correct. Sure, if you just need to call show directly, you can do asShowable like that, but that's just the simplest case. Imagine you needed to pass the value to another function that wanted to show it later? And then imagine it was a list of values, not a single one:
let needsToShow (showable: IShowable) (xs: 'a list) =
xs |> List.iter (fun x -> ??? how do I show `x` ???)
No, this wouldn't do of course. The key is that Show should be a function 'a -> string, not unit -> string. And this means that IShowable itself should be generic:
// Haskell: class Showable a where show :: a -> String
type IShowable<'a> with
abstract member Show : 'a -> string
// Haskell: instance Showable Foo where show (Foo i) = show i
module Foo =
let showable = { new IShowable<Foo> with member _.Show foo = string foo.Foo }
// Haskell: needsToShow :: Show a => [a] -> IO ()
let needsToShow (showable: IShowable<'a>) (xs: 'a list) =
xs |> List.iter (fun x -> printfn "%s" (showable.Show x))
// Haskell: needsToShow [Foo 1, Foo 42]
needsToShow Foo.showable [ { Foo: 1 }; { Foo: 42 } ]
And this is, essentially, what type classes are: they're indeed merely dictionaries of functions that are passed everywhere as extra parameters. Every type has such dictionary either available right away (like Foo above) or constructable from other such dictionaries, e.g.:
type Bar<'a> = Bar of 'a
// Haskell: instance Show a => Show (Bar a) where show (Bar a) = "Bar: " <> show a
module Bar =
let showable (showA: IShowable<'a>) =
{ new IShowable<Bar<'a>> with member _.Show (Bar a) = "Bar: " + showA.Show a }
This is completely equivalent to type classes. And in fact, this is exactly how they're implemented in languages like Haskell or PureScript in the first place: like dictionaries of functions being passed as extra parameters. It's not a coincidence that constraints on function type signatures even kinda look like parameters - just with a fat arrow instead of a thin one.
The only real difference is that in F# you have to do that yourself, while in Haskell the compiler figures out all the instances and passes them for you.
And this difference turns out to be kind of important in practice. I mean, sure, for such a simple example as Show for the immediate parameter, you can just pass the damn instance yourself. And even if it's more complicated, I guess you could suck it up and pass a dozen extra parameters.
But where this gets really inconvenient is operators. Operators are functions too, but with operators there is nowhere to stick an extra parameter (or dozen). Check this out:
x = getY >>= \y -> getZ y <&> \z -> y + 42 > z
Here I used four operators from four different classes:
>>= comes from Monad
<&> from Functor
+ from Num
> from Ord
An equivalent in F# with passing instances manually might look something like:
let x =
bind Foo.monad getY <| fun y ->
map Bar.functor (getZ y) <| fun z ->
gt Int.ord (add Int.num y 42) z
Having to do that everywhere is quite unreasonable, you have to agree.
And this is why many F# operators either use SRTPs (e.g. +) or rely on "known" interfaces (e.g. <) - all so you don't have to pass instances manually.

OCaml Parsing String into String*Int list

type unit_t = (string * int) list
How would I go about creating an expression to parse a string into this form? Do I need to implement code in a parser.mly format in order to handle this?
There's no real way to give a detailed answer, since you don't say how the original string is supposed to correspond to your list of pairs.
Based just on the simplicity of your output type, I'd say you could do this without invoking the full machinery of ocamlyacc. I.e., I doubt you need a parser.mly file. You could use ocamllex, or you could just apply some regular expressions from the Str module. It depends on what your parsing actually needs to do.
Here's one possibility that uses regular expressions from Str:
let p s =
let fs = Str.full_split (Str.regexp "[0-9]+") s in
let rec go = function
| [] -> []
| Str.Text s :: Str.Delim i :: rest -> (s, int_of_string i) :: go rest
| Str.Text s :: rest -> (s, 0) :: go rest
| Str.Delim i :: rest -> ("", int_of_string i) :: go rest
in
go fs
You can run it like this:
# #load "str.cma";;
# #use "p.ml";;
val p : string -> (string * int) list = <fun>
# p "123abc456def";;
- : (string * int) list = [("", 123); ("abc", 456); ("def", 0)]
# p "ghi789jkl100";;
- : (string * int) list = [("ghi", 789); ("jkl", 100)]

Simply parse command line args

I want to use the following code to restrict there is only one argument. However, I got the following error at first :: NIL?
Error 1 This expression was expected to have type
string []
but here has type
'a list
[<EntryPoint>]
let main argv =
match argv with
| first :: NIL ->
.... do something with first
| _ -> failwith "Must have only one argument."
The command line arguments are passed as an array, not a list.
Do something like this if you expect exactly one argument:
match argv with
| [|first|] ->
// .... do something with first
| _ -> failwith "Must have only one argument."
As mentioned in the accepted answer the "args" argument to the entrypoint is an array, not a list, so you cannot use it with the syntax for list matching.
Instead of matching on the array, as suggested above, you could turn the arguments into an actual list and use that for matching. I have found that a very useful way to handlie command line arguments (though it may be overkill for your example case). As an example:
[<EntryPoint>]
let main args =
let arglist = args |> List.ofSeq
match arglist with
| first :: [] ->
// do something with 'first'
| _ -> // catches both the no-argument and multi-argument cases
printfn "Usage : "
// print usage message
Edit:
As for more complicated examples there are two ways to go from here. You can of course add more complicated cases in the match, or you could parse the list of arguments in a recursive way to build an object representing options and arguments. The latter would get a bit too complicated to fit here, but as an example of some more complex match cases, here is some code related to some recent work where the executable accepts a "command" to operate on a target file, and each command has different further arguments (each command calls a function whose implementation I left out for sake of brevity)
[<EntryPoint>]
let main args =
let arglist = args |> List.ofSeq
match arglist with
| target :: "list" :: [] ->
listContent target
| target :: "remove" :: name :: [] ->
removeContent target name
| target :: "add" :: name :: [] ->
addContent target name
| target :: "addall" :: names ->
for name in names do
addContent target name
| _ -> // catches cases not covered above
printfn "Usage : "
// print usage message
How about Active Patterns for parsing individual commands, returning an Option indicating None on failure and Some with the content of recovered parameters, possibly nestled in their own dedicated type. Converting "argv" to "string list" is merely a convenience act due to the convenience of list syntax in F#. Note: there are a lot of type annotations here that are typically unnecessary.
type Cmd1Parms = ....
type Cmd2Parms = ....
let performCmd1 cmd1Parms = ...
let performCmd2 cmd2Parms = ...
let commandNotFound argL = ...
let (|ParseForCmd1|_|) argL : Cmd1Parms option = ....
let (|ParseForCmd2|_|) argL : Cmd2Parms option = ....
[<EntryPoint>]
let main argv =
let argL = List.ofSeq<string> argv
match argL with
| ParseForCmd1 cmd1Parms -> performCmd1 cmd1Parms
| ParseForCmd2 cmd2Parms -> performCmd2 cmd2Parms
| _ -> commandNotFound argL

Monadic parse with uu-parsinglib

I'm trying to create a Monadic parser using uu_parsinglib. I thought I had it covered, but I'm getting some unexpected results in testing
A cut down example of my parser is:
pType :: Parser ASTType
pType = addLength 0 $
do (Amb n_list) <- pName
let r_list = filter attributeFilter n_list
case r_list of
(ASTName_IdName a : [] ) -> return (ASTType a)
(ASTName_TypeName a : [] ) -> return (ASTType a)
_ -> pFail
where nameFilter :: ASTName' -> Bool
nameFilter a =
case a of
(ASTName_IDName _) -> True
(ASTName_TypeName _) -> True
_ -> False
data ASTType = ASTType ASTName
data ASTName = Amb [ASTName']
data ASTName' =
ASTName_IDName ASTName
ASTName_TypeName ASTName
ASTName_OtherName ASTName
ASTName_Simple String
pName is an ambiguous parser. What I want type parser to do is apply a post filter, and return all alternatives that satisfy nameFilter, wrapped as ASTType.
If there are none, it should fail.
(I realise the example I've given will fail if there is more than one valid match in the list, but the example serves its purpose)
Now, this all works as far as I can see. The problem lies when you use it in more complicated Grammars, where odd matches seem to occur. What I suspect is the problem is the addLength 0 part
What I would like to do is separate out the monadic and applicative parts. Create a monadic parser with the filtering component, and then apply pName using the <**> operator.
Alternatively
I'd settle for a really good explanation of what addLength is doing.
I've put together a fudge/workaround to use for monadic parsing with uu-parsinglib. The only way I ever use Monadic parsers is to analysis a overly generous initial parser, and selectively fail its results.
bind' :: Parser a -> (a -> Parser b) -> Parser b
bind' a#(P _ _ _ l') b = let (P t nep e _) = (a >>= b) in P t nep e l'
The important thing to remember when using this parser is that
a -> M b
must consume no input. It must either return a transformed version of a, or fail.
WARNING
Testing on this is only minimal currently, and its behaviour is not enforced by type. It is a fudge.

Type unit does not have null as a proper value

Below I post a fragment of my F# program that causes problems.
...
match words with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = new FuzzyVariable(name, context, Double.Parse value)
fuzzyVars <- var :: fuzzyVars
In line:
fuzzyVars <- var :: fuzzyVars
I get "Type unit does not have null as a proper value" error. I am fairly new to F# programming and I don't quite know what might be causing this issue.
fuzzyVars is of type FuzzyVariable list. FuzzyVariable is a custom defined type.
EDIT.
As #Tomas Petricek pointed out there was a line in my code that returned null:
| [] -> null
My intention was to ignore value of the match. The proper way to do it is:
| [] -> ()
After that change everything works fine.
As already mentioned, the problem is not in the piece of code you posted - it looks like some other part of your program makes the F# compiler think that the expression fuzzyVars <- var :: fuzzyVars should have a type that admits null (but that's not the case, because it returns unit).
I was able to get the same error by writing:
open System
type FuzzyVariable(a:string, b:string, c:float) =
member x.A = ""
let mutable fuzzyVars : (FuzzyVariable list) = []
let words = [null; "of"; "context"; "="; "5"]
And the main part:
null = (match words with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = new FuzzyVariable(name, context, Double.Parse value)
fuzzyVars <- var :: fuzzyVars)
You probably do not have something like this in your code :-) but perhaps the error message might give you a pointer to where the null comes from. Here, I get:
error FS0001: The type 'unit' does not have 'null' as a proper value. See also C:\Users\Tomas\AppData\Local\Temp\~vs648E.fsx(8,0)-(8,4).
And the code on line 8 between character 0 and 4 is the null value! So perhaps check out whether the error message gives you some more information? Or try looking for null elsewhere in your code... (It might be also caused by some unexpected indentation.)
I tried this and it compiled just fine:
open System
type test = {Name:string}
let mutable fuzzyVars : (test list) = []
match [null; "of"; "context"; "="; "5"] with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = {Name=name}
fuzzyVars <- var :: fuzzyVars
| a -> a |> ignore
The problem isn't in this section of code.

Resources