Questions on tuples and user input in F# - f#

I'm trying to play around with f# to get down the basics but stuck. If you have general tips it would be greatly appreciated.
#light
open System
[<EntryPoint>]
let main (args : string[]) =
match args with
| [| firstName; lastName; city |] ->
printfn "Hi there %s %s from %s" firstName lastName city
0
| _ -> failwith "Usage: HiThere.exe firstName lastName City";;
I get this error,
val main : args:string [] -> int
I was watching a tutorial on f# and trying to learn this function but I don't understand why I can't do it without these errors.

There is a very minor typo in args.[0], args.[1]. args.[2]. You have a . rather than a , between the second and third element - it should be args.[0], args.[1], args.[2].
The compiler is still able to parse it, but it interprets your code as:
args.[0], (args.[1].args.[2])
This is syntactically a two-element tuple and you are assigning it to a three-element tuple, so you get the error about tuples first. It would fail later because args is not a member of args.[1], but that's a separate message (that the compiler ignores because it reports the one it finds earlier).
As a side-note, you could also use pattern matching on arrays and write:
let main (args : string[]) =
match args with
| [| firstName; lastName; city |] ->
printfn "Hi there %s %s from %s" firstName lastName city
0
| _ -> failwith "Usage: HiThere.exe firstName lastName City"

Related

A better way to use Seq.fold in F#

I wrote a small console app that update a Type record without using any mutable variable. If that looks simple for seasoned functional programmers, it was quite a hard work for me.
It works, but there is one thing I am not happy with. But before that, let's start with the code:
open System
//------------------------------------------------------------------------------------
// Type, no data validation to keep it simple
//------------------------------------------------------------------------------------
[<StructuredFormatDisplay("{FirstName} {LastName} is a {Age} year old {Sex}")>]
type Student = {
FirstName: string
LastName : string
Sex : char
Age: int
}
//------------------------------------------------------------------------------------
// I/O functions
//------------------------------------------------------------------------------------
let getConsoleChar message =
printf "\n%s" message
Console.ReadKey().KeyChar
let getConsoleString message =
printf "\n%s" message
Console.ReadLine()
let getConsoleInt = getConsoleString >> Int32.Parse //no tryparse to keep it simple, I'm sure you can type an integer
let isValidCommand command = [ 'f'; 'l'; 's'; 'a'; 'x'] |> List.contains command
let isStopCommand = (=) 'x'
let processCommand student command =
match command with
| 'f' -> { student with FirstName = (getConsoleString "First Name: ")}
| 'l' -> { student with LastName = (getConsoleString "Last Name: ")}
| 's' -> { student with Sex = (getConsoleChar "Sex: ")}
| 'a' -> { student with Age = (getConsoleInt "Age: ")}
| 'x' -> student
| _ -> failwith "You've just broken the Internet, theorically you cannot be here"
//------------------------------------------------------------------------------------
// Program
//------------------------------------------------------------------------------------
let initialStudent = {
FirstName = String.Empty
LastName = String.Empty
Sex = Char.MinValue
Age = 0
}
let commands = seq {
while true do
yield getConsoleChar "Update [f]irst name, [l]ast name, [s]ex, [a]ge or e[x]it: " }
let finalStudent =
commands
|> Seq.filter isValidCommand
|> Seq.takeWhile (not << isStopCommand)
|> Seq.map (fun cmd -> (initialStudent, cmd))
|> Seq.fold (fun student studentAndCommand -> processCommand student (snd studentAndCommand)) initialStudent
printfn "\n<<<< %A >>>>\n" finalStudent
My problem is with
|> Seq.map (fun cmd -> (initialStudent, cmd))
|> Seq.fold (fun student studentAndCommand -> processCommand student (snd studentAndCommand)) initialStudent
It looks bizarre to transform a sequence of char into a Student*char to be able to plug it with aSeq.fold. Also, if using the initialStudent as a starting point for Seq.fold is logical, it feel weird to use it in the mapping transformation (I'm not sure anyone would understand the logic if this code was pushed in prod).
Is there a better way to treat the sequence of commands or is this code standard and acceptable in the functional world?
You can get rid of the map and simplify the fold considerably:
commands
|> Seq.filter isValidCommand
|> Seq.takeWhile (not << isStopCommand)
|> Seq.fold processCommand initialStudent
I'm not sure why you thought you had to map the seq<char> into a seq<Student * char> to begin with. Since you immediately use snd to extract the char from the tuple, undoing the map, the tuples' first elements are totally ignored. Much cleaner to simply avoid creating tuples in the first place

What those F# functions are supposed to do?

Learning F# these days, I've noticed that in some libraries like this one or that one
there are some similar functions which seem to be common in F# but can't really decipher them, what are they doing, what are they for?
let ap x f =
match f, x with
| Ok f , Ok x -> Ok (f x)
| Error e , _ -> Error e
| _ , Error e -> Error e
let inline (<*>) f x = ap x f
let inline (<!>) f x = Result.map f x
let inline lift2 f a b = f <!> a <*> b
Even aggregating comments with them does not really help in my understanding:
/// Sequential application
/// If the wrapped function is a success and the given result is a success the function is applied on the value.
/// Otherwise the exisiting error messages are propagated.
let ap x f =
match f,x with
| Ok f , Ok x -> Ok (f x)
| Error e , _ -> Error e
| _ , Error e -> Error e
/// Sequential application
/// If the wrapped function is a success and the given result is a success the function is applied on the value.
/// Otherwise the exisiting error messages are propagated.
let inline (<*>) f x = ap x f
/// Infix map, lifts a function into a Result and applies it on the given result.
let inline (<!>) f x = Result.map f x
/// Promote a function to a monad/applicative, scanning the monadic/applicative arguments from left to right.
let inline lift2 f a b = f <!> a <*> b
I don't even see an example of how they could be used, not sure also why inline has been used.
If there is somebody who could hint about how useful those functions are, I would greatly appreciate.
These are called "applicative functors" (sometimes just "applicatives"). Their purpose is to combine data from multiple Something<'T> using a function. Basically, "lifting" a function of type 'Arg1 -> 'Arg2 -> ... -> 'Result into a function of type Something<'Arg1> -> Something<'Arg2> -> ... -> Something<'Result>.
For example, given the standard Result type:
type Result<'T, 'Err> = Ok of 'T | Error of 'Err
you may have several Result values that you want to combine together. For example, say you have a form with inputs firstName, lastName and age. You also have a result type Person:
type Person = { firstName: string; lastName: string; age: int }
// string -> string -> int -> Person
let makePerson firstName lastName age =
{ firstName = firstName; lastName = lastName; age = age }
The values coming from your actual form may have type Result<string, InputError> or Result<int, InputError>, which can be Error if eg. the user hasn't entered a value.
type InputError =
| FieldMissing of fieldName: string
// Other error cases...
You want to combine them into a Result<Person, InputError>, which is Ok if all inputs are Ok, or Error if any input is Error. Using the applicative, you can do it like this:
// Result<string, InputError> -> Result<string, InputError> -> Result<int, InputError> -> Result<Person, InputError>
let makePersonResult firstName lastName age =
makePerson <!> firstName <*> lastName <*> age
// Example uses:
makePersonResult (Ok "John") (Ok "Doe") (Ok 42)
// --> Ok { firstName = "John"; lastName = "Doe"; age = 42 }
makePersonResult (Error (FieldMissing "firstName")) (Ok "Doe") (Ok 42)
// --> Error (FieldMissing "firstName")
A similar concept can be applied to many other types than Result, which is why it was given a name. For example, an applicative on Async<'T> could run all the argument Asyncs in parallel, and when they're finished, combine their results into an Async<'Result>. Another example, an applicative on 'T list would be equivalent to the standard library's List.map2 or List.map3 but generalizable to any number of argument lists.
Side note: if you look up "applicative functor", most of the results you'll find will be in Haskell, where the map operator, usually written <!> in F#, is written <$> instead.
Scott Wlaschin's F# for fun and profit (https://fsharpforfunandprofit.com) has a series Map and Bind and Apply, Oh my! (https://fsharpforfunandprofit.com/posts/elevated-world-7) which should be able to shed more light on this. Regarding your particular question:
<!> is the map operator which applies a function f and a parameter x to elements of the data structure you are mapping over, or in other words, lifts the function into the realm of the data structure, in this case the Result type.
<*> is the ap (apply) operator which unpacks a function wrapped inside a elevated value into a lifted function.
lift2 is basically the map operator for a two-parameter function.
Please have a look at the blog, it really helps!

Dynamic Lookup in F#

Can somebody help me with article of Tomas Petricek: http://tomasp.net/blog/fsharp-dynamic-lookup.aspx/#dynfslinks?
The problem is that it is severely outdated. I understand that namespaces
open Microsoft.FSharp.Quotations.Typed
open Microsoft.FSharp.Quotations.Raw
are gone. So I removed the openings. But there are still errors. "Typed" is not defined. "RecdGet" is not defined. And I suspect they are not the last. I'm trying to prove to my boss that F# is good to use for database normalization. Dynamic lookup of fields would really helped me to deal with similarly named fields having different prefixes.
There is also post of Tomas on fpish: https://fpish.net/topic/None/57493, which I understand predates the article
Here's a rough equivalent:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
type DynamicMember<'t,'u> = Expr<'t -> 'u>
let getValueReader (expr:DynamicMember<'recdT, 'fieldT>) =
// Match the quotation representing the symbol
match expr with
| Lambda(v, PropertyGet (Some (Var v'), pi, [])) when v = v' ->
// It represents reading of the F# record field..
// .. get a function that reads the record field using F# reflection
let rdr = Reflection.FSharpValue.PreComputeRecordFieldReader pi
// we're not adding any additional processing, so we just
// simply add type conversion to the correct types & return it
((box >> rdr >> unbox) : 'recdT -> 'fieldT)
| _ ->
// Quotation doesn't represent symbol - this is an error
failwith "Invalid expression - not reading record field!"
type SampleRec = { Str : string; Num : int }
let readStrField = getValueReader <# fun (r : SampleRec) -> r.Str #>
let readNumField = getValueReader <# fun (r : SampleRec) -> r.Num #>
let rc = { Str = "Hello world!"; Num = 42 }
let s, n = readStrField rc, readNumField rc
printfn "Extracted: %s, %d" s n

Can a provided type be used in a quotation - Do TypeProvider calls appear in ReflectedDefinition functions?

I'd like to generate a type with static functions, that I can then use in functions that become quotations using the ReflectedDefinition attribute. It seems to me a convenient way of translating something into FSharp types, using FSharp to compose the domain of functions and types, and spit the composed code back into its native form, having received the benefit of type checking, VS intellisense, higher order functions, etc. To try and get started I have this type provider, largely copy->pasted from various articles
[<TypeProvider>]
type CSoundTypeProvider(config: TypeProviderConfig) as this =
inherit ProvidedTypes.TypeProviderForNamespaces()
let namespaceName = "TestNamespace"
let thisAssembly = Assembly.GetExecutingAssembly()
// config.
let intType = typeof<int>
let providedParam = ProvidedTypes.ProvidedParameter("prm", intType)
let providedFunction = ProvidedTypes.ProvidedMethod("TestMethod", [providedParam], intType, IsStaticMethod=true
, InvokeCode = fun args ->
// The 'args' parameter represents expressions that give us access to the
// instance on which the method is invoked and other parameters (if there are more)
let instance = args.[0]
// Now we can return quotation representing a call to MethodInfo 'p' with 'instance'
instance)
let csoundProvidedWrapper = ProvidedTypes.ProvidedTypeDefinition(thisAssembly, namespaceName, "TestType", None)
do csoundProvidedWrapper.AddMember(providedFunction)
do this.AddNamespace(namespaceName, [csoundProvidedWrapper])
And testing it with this reflected definition:
[<ReflectedDefinition>]
let myfn i j =
let k = i * j
let x = k + 2
let f = TestNamespace.TestType.TestMethod k
let ret = f + 2
ret
I'm parsing the reflected definition like this:
<# myfn #> |> println
println is a function (copied from another article) that has many of the active patterns for parsing quotations like Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList), which gets me an experssion tree of all of the code, except for the provided static method. Is what I'm trying to do even possible? If so, what's the active pattern I've likely missed from my println function here:
let println expr =
let rec print expr = match expr with
| Patterns.Application(expr1, expr2) ->
// Function application.
print expr1
printf " "
print expr2
| Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList) ->
print n
| Patterns.Call(exprOpt, methodInfo, exprList) ->
// Method or module function call.
match exprOpt with
| Some expr -> print expr
| None -> printf "%s" methodInfo.DeclaringType.Name
printf ".%s(" methodInfo.Name
if (exprList.IsEmpty) then printf ")" else
print exprList.Head
for expr in exprList.Tail do
printf ","
print expr
printf ")"
| DerivedPatterns.Int32(n) ->
printf "%d" n
| Patterns.Lambda(param, body) ->
// Lambda expression.
printf "fun (%s:%s) -> " param.Name (param.Type.ToString())
print body
| Patterns.Let(var, expr1, expr2) ->
// Let binding.
if (var.IsMutable) then
printf "let mutable %s = " var.Name
else
printf "let %s = " var.Name
print expr1
printf " in "
print expr2
| Patterns.PropertyGet(_, propOrValInfo, _) ->
printf "%s" propOrValInfo.Name
| DerivedPatterns.String(str) ->
printf "%s" str
| Patterns.Value(value, typ) ->
printf "%s" (value.ToString())
| Patterns.Var(var) ->
printf "%s" var.Name
| _ -> printf "%s" (expr.ToString())
print expr
If I can't do this, what approach would you recommend for generating FSharp definitions that I can use in quotations? I've largely been influenced by the FunScript project, but hoping to avoid the step where it seems each Typescript definition has to get compiled into a seperate DLL.
Most of the type provider demos out there use erased type providers which do not produce actual .NET types. When you use an erased type provider, the generated methods are erased and replaced with the code you provided in the method's InvokeCode.
Let's say you have a method Foo that erases to someFunc with "Foo" as an argument:
myObj.Foo() ~> someFunc(myObj, "Foo")
In quotations, you will also see the erased version (both in direct <# .. #> and in ReflectedDefinition):
<# myObj.Foo() #> ~> <# someFunc(myObj, "Foo") #>
The way FunScript type provider works is that it generates some dummy code that contains the function name so that it can then generate the corresponding JavaScript. Say you have:
<# win.Alert(arg) #> ~> <# invokeFunction("alert", win, arg) #>
To do the same sort of thing, you'll need to define a function like invokeFunction and to generate appropriate InvokeCode. Then you can look for calls to invokeFunction in the generated quotation and do whatever special thing you need to do there. It is a bit hard to see what exactly are you trying to do, but this should at least point you in the right direction.

F# quotations object graph

In C# I could create a string representation of an object graph fairly easily with expression trees.
public static string GetGraph<TModel, T>(TModel model, Expression<Func<TModel, T>> action) where TModel : class
{
var method = action.Body as MethodCallExpression;
var body = method != null ? method.Object != null ? method.Object as MemberExpression : method.Arguments.Any() ? method.Arguments.First() as MemberExpression : null : action.Body as MemberExpression;
if (body != null)
{
string graph = GetObjectGraph(body, typeof(TModel))
return graph;
}
throw new Exception("Could not create object graph");
}
In F# I've been looking at Quotations to attempt to do the same thing, and can't quite figure it out. I've attempted converting the quotation into an Expression using the PowerPack libraries, but have had no luck so far, and the information on the internet seems fairly sparse on this topic.
If the input is:
let result = getGraph myObject <# myObject.MyProperty #>
the output should be "myobject.MyProperty"
You can see what you get from quotation expression in fsi session:
> let v = "abc"
> <# v.Length #>;;
val it : Expr<int>
= PropGet (Some (PropGet (None, System.String v, [])), Int32 Length, [])
> <# "abc".Length #>;;
val it : Expr<int>
= PropGet (Some (Value ("abc")), Int32 Length, [])
You can find description of all active patterns available to parse qoutations into
manual\FSharp.Core\Microsoft.FSharp.Quotations.Patterns.html
under your F# installation directory or at msdn site
There is nice Chris Smith's book "Programming F#" with chapter named "Quotations" :)
So, after all, just try to write simple parser:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Quotations.DerivedPatterns
let rec getGraph (expr: Expr) =
let parse args =
List.fold_left (fun acc v -> acc ^ (if acc.Length > 0 then "," else "") ^ getGraph v) "" args
let descr s = function
| Some v -> "(* instance " ^ s ^ "*) " ^ getGraph v
| _ -> "(* static " ^ s ^ "*)"
match expr with
| Int32 i -> string i
| String s -> sprintf "\"%s\"" s
| Value (o,t) -> sprintf "%A" o
| Call (e, methodInfo, av) ->
sprintf "%s.%s(%s)" (descr "method" e) methodInfo.Name (parse av)
| PropGet(e, methodInfo, av) ->
sprintf "%s.%s(%s)" (descr "property" e) methodInfo.Name (parse av)
| _ -> failwithf "I'm don't understand such expression's form yet: %A" expr
P.S. And of course you will need some code to translate AST to human readable format.
I'm unsure what the state of things was back when you asked this question, but today you can convert an F# Quotation to an Expression using the PowerPack like so:
<# "asdf".Length #>.ToLinqExpression()
Also, I've been developing a library Unquote which is able to decompile many F# Quotations into F# single-line non-light syntax code. It can easily handle simple instance PropertyGet expressions like your required input / output:
> decompile <# "asdf".Length #>;;
val it : string = ""asdf".Length"
See my answer to a similar question for more information or just visit Unquote's home page.

Resources