How to add instances of sub types that have common base class to the same list in FSharp? - f#

I have a base abstract class named Tokenand some sub types like NumToken,StrToken.
I want to put their instances to the same list.
I can't declare a variable use let l = list<'a when 'a :> Token>
Then, I write
let extractToken<'a when 'a :> Token>(lineNum:int, line:string) : 'a list option =
let mutable result : 'a list = []
It works, but can not add element.result <- new NumToken(lineNum, value) :: result just say it needs 'a but here is NumToken
Now I can use new NumToken(lineNum, value) :> Token and declare Token list.
It wokrs but looks ugly(I know fsharp doesn't do auto up cast..).
list<_ :> Token> doesn't work too, it only accepts one sub type.
Thx for help.

When you model tokens using a class hierarchy and you create a list of tokens, the type of the list needs to be specific. You can either return list<Token> or list<NumToken>.
The flexible types with when constraints are useful only quite rarely - typically, when you have a function that takes some other function and returns whatever the other function produces, so I do not think you need them here. You can use list<Token> and write:
result <- (NumToken(lineNum, value) :> Token) :: result
That said, modelling token in F# using a class hierarchy is not very good idea. F# supports discriminated unions, which are much better fit for this kind of problem:
type Token =
| NumToken of int
| StrToken of string
Then you can write a function that returns list<Token> just by writing
result <- (NumToken 42) :: result
Although, depending on what you are doing, it might be also a good idea to avoid the mutation.

Related

This expression was expected to have type 'unit' but here has type 'string'

I was attempting to convert this to F# but I can't figure out what I'm doing wrong as the error message (in title) is too broad of an error to search for, so I found no resolutions.
Here is the code:
let getIP : string =
let host = Dns.GetHostEntry(Dns.GetHostName())
for ip in host.AddressList do
if ip.AddressFamily = AddressFamily.InterNetwork then
ip.ToString() // big fat red underline here
"?"
A for loop in F# is for running imperative-style code, where the code inside the for loop does not produce a result but instead runs some kind of side-effect. Therefore, the expression block in an F# for loop is expected to produce the type unit, which is what side-effect functions should return. (E.g., printfn "Something" returns the unit type). Also, there's no way to exit a for loop early in F#; this is by design, and is another reason why a for loop isn't the best approach to do what you're trying to do.
What you're trying to do is go through a list one item at a time, find the first item that matches some condition, and return that item (and, if the item is not found, return some default value). F# has a specialized function for that: Seq.find (or List.find if host.AddressList is an F# list, or Array.find if host.AddressList is an array. Those three functions take different input types but all work the same way conceptually, so from now on I'll focus on Seq.find, which takes any IEnumerable as input so is most likely to be what you need here).
If you look at the Seq.find function's type signature in the F# docs, you'll see that it is:
('T -> bool) -> seq<'T> -> 'T
This means that the function takes two parameters, a 'T -> bool and seq<'T> and returns a 'T. The 'T syntax means "this is a generic type called T": in F#, the apostrophe means that what follows is the name of a generic type. The type 'T -> bool means a function that takes a 'T and returns a Boolean; i.e., a predicate that says "Yes, this matches what I'm looking for" or "No, keep looking". The second argument to Seq.find is a seq<'T>; seq is F#'s shorter name for an IEnumerable, so you can read this as IEnumerable<'T>. And the result is an item of type 'T.
Just from that function signature and name alone, you can guess what this does: it goes through the sequence of items and calls the predicate for each one; the first item for which the predicate returns true will be returned as the result of Seq.find.
But wait! What if the item you're looking for isn't in the sequence at all? Then Seq.find will throw an exception, which may not be the behavior you're looking for. Which is why the Seq.tryFind function exists: its function signature looks just like Seq.find, except for the return value: it returns 'T option rather than 'T. That means that you'll either get a result like Some "ip address" or None. In your case, you intend to return "?" if the item isn't found. So you want to convert a value that's either Some "ip address or None to either "ip address" (without the Some) or "?". That is what the defaultArg function is for: it takes a 'T option, and a 'T representing the default value to return if your value is None, and it returns a plain 'T.
So to sum up:
Seq.tryFind takes a predicate function and a sequence, and returns a 'T option. In your case, this will be a string option
defaultArg takes a 'T option and a default value, and returns a normal 'T (in your case, a string).
With these two pieces, plus a predicate function you can write yourself, we can do what you're looking for.
One more note before I show you the code: you wrote let getIP : string = (code). It seems like you intended for getIP to be a function, but you didn't give it any parameters. Writing let something = (code block) will create a value by running the code block immediately (and just once) and then assigning its result to the name something. Whereas writing let something() = (code block) will create a function. It will not run the code block immediately, but it will instead run the code block every time the function is called. So I think you should have written let getIP() : string = (code).
Okay, so having explained all that, let's put this together to give you a getIP function that actually works:
let getIP() = // No need to declare the return type, since F# can infer it
let isInternet ip = // This is the predicate function
// Note that this function isn't accessible outside of getIP()
ip.AddressFamily = AddressFamily.InterNetwork
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = Seq.tryFind isInternet host.AddressList
defaultArg maybeIP "?"
I hope that's clear enough; if there's anything you don't understand, let me know and I'll try to explain further.
Edit: The above has one possible flaw: the fact that F# may not be able to infer the type of the ip argument in isInternet without an explicit type declaration. It's clear from the code that it needs to be some class with an .AddressFamily property, but the F# compiler can't know (at this point in the code) which class you intend to pass to this predicate function. That's because the F# compiler is a single-pass compiler, that works its way through the code in a top-down, left-to-right order. To be able to infer the type of the ip parameter, you might need to rearrange the code a little, as follows:
let getIP() = // No need to declare the return type, since F# can infer it
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = host.AddressList |> Seq.tryFind (fun ip -> ip.AddressFamily = AddressFamily.InterNetwork)
defaultArg maybeIP "?"
This is actually more idiomatic F# anyway. When you have a predicate function being passed to Seq.tryFind or other similar functions, the most common style in F# is to declare that predicate as an anonymous function using the fun keyword; this works just like lambdas in C# (in C# that predicate would be ip => ip.AddressFamily == AddressFamily.InterNetwork). And the other thing that's common is to use the |> operator with things like Seq.tryFind and others that take predicates. The |> operator basically* takes the value that's before the |> operator and passes it as the last parameter of the function that's after the operator. So foo |> Seq.tryFind (fun x -> xyz) is just like writing Seq.tryFind (fun x -> xyz) foo, except that foo is the first thing you read in that line. And since foo is the sequence that you're looking in, and fun x -> xyz is how you're looking, that feels more natural: in English, you'd say "Please look in my closet for a green shirt", so the concept "closet" comes up before "green shirt". And in idiomatic F#, you'd write closet |> Seq.find (fun shirt -> shirt.Color = "green"): again, the concept "closet" comes up before "green shirt".
With this version of the function, F# will encounter host.AddressList before it encounters fun ip -> ..., so it will know that the name ip refers to one item in host.AddressList. And since it knows the type of host.AddressList, it will be able to infer the type of ip.
* There's a lot more going on behind the scenes with the |> operator, involving currying and partial application. But at a beginner level, just think of it as "puts a value at the end of a function's parameter list" and you'll have the right idea.
In F# any if/else/then-statement must evaluate to the same type of value for all branches. Since you've omitted the else-branch of the expression, the compiler will infer it to return a value of type unit, effectively turning your if-expression into this:
if ip.AddressFamily = AddressFamily.InterNetwork then
ip.ToString() // value of type string
else
() // value of type unit
Scott Wlaschin explains this better than me on the excellent F# for fun and profit.
This should fix the current error, but still won't compile. You can solve this either by translating the C#-code more directly (using a mutable variable for the localIP value, and doing localIP <- ip.ToString() in your if-clause, or you could look into a more idiomatic approach using something like Seq.tryFind.

Can I Access Parameters of a Computation Expression?

Is it possible to create methods or stand-alone functions in a computation expression that can later be used by one of the canonical methods of a computation expression?
I want something like this:
type FormletBuilder(ctx : HttpContext) =
let get_int =
match Int32.TryParse (ctx.Request.["foo"]) with
| (true, n) -> Some n
| _ -> None
//similar definitions for get_date, get_non_empty_str, etc...
member x.Bind (read : 'a option, f : 'a -> option 'a) =
match read with
| Some x -> f(x)
| None -> None
member x.Return (obj) = Some obj
member x.Zero () = None
let person = formlet ctx {
let! id = get_int "id"
let! name = get_non_empty_str "fullname"
return Person(id, name)
}
But the compiler complains that get_int is not defined.
let bindings in class definitions are always private. You can define a member instead.
For an easy solution, you could do:
let formlet = FormletBuilder(ctx)
let person = formlet {
let! id = formlet.get_int "id"
...
}
I understand now that what you actually want is a maybe monad, and the workflow argument is there just to make use of some syntactic sugar? If so, there are a couple other things you can consider doing:
Go Haskell on it all the way and implement a MaybeReader monad, so that both the maybe and the reader parts of it are explicit in type,
Put the sugar away - I understand you don't actually need the context in any core builder members? If so, than maybe it had no business being an argument to the builder in the first place. Have a 'clean' maybe monad, move get_int etc. into a proper module and have them take HttpContext explicitly as an argument.
If you're using F# 3.0 or later, you can define get_int etc. as custom operations of the workflow, which should effectively give you the nice syntax you want to have. Here's a good post about it by Tomas Petricek.
Combine 2. and 3. - instead of a large number of custom operations, have one - ask - which will take an HttpContext -> 'a function and apply ctx to it. Effectively a bastardized version of reader. Then you can move your get_int etc. into a proper module.

Playing with F# types and getting lost

I have been doing a little reading on F# and decided to give it a try. I started with a somewhat involved example and I came up with and got lost immediately. I wonder if someone can share some thoughts on it.
I wanted to write a method called ComparisonStrategy<'T> that returns an instance of IEqualityComparer<'T>. It that takes in a variable length of ComparisonWhichAndHow<'T> instances. The type ComparisonWhichAndHow<'T> can either be:
One function of type ('T -> *), which is a method that selects a single field to compare
a 2-tuple of ('T -> 'U, IEqualityComparer<'U>) if you don't want the default Equals or GetHashCode to be used on 'U.
I have tried to draw this down on visual studio for a while now, but I can't even get the function declaration part right. I am somewhat positive I would be able to implement the method body if I can just get past this, but seems like I can't.
Edited:
This is the code I have tried so far.
I am trying to achieve the 2 following things.
Come up with a generic way of generating a equal method for each object.
Sometimes some business operations might require comparing some fields of 2 objects, and some fields of their children. Not a full comparison. I am trying to make writing those code more concise and simple
This is what I have so far:
module Failed =
open System.Collections.Generic
open System
type ComparsionOption<'T, 'U> =
| Compare of ('T -> 'U)
| CompareWith of ('T -> 'U) * IEqualityComparer<'U>
// TO USE: [<ParamArray>]
// TODO: this method returns a dummy for now
let CompareStrategy (opts : ComparsionOption<'T, _> array) =
EqualityComparer<'T>.Default
// How it's used
type Person(name : string, id : Guid) =
member this.Name = name
member this.ID = id
let fullCompare : EqualityComparer<Person> =
CompareStrategy [|Compare(fun (p : Person) -> p.Name);
CompareWith((fun (p : Person) -> p.ID), EqualityComparer<Guid>.Default)|] // error here
Looking at the problem from another perspective, it looks like you want to be able to construct objects that perform comparison in two different ways (which you specified) and then compose them.
Let's start by looking at the two ways to build an object that performs comparison. You can represent both by IEqualityComparer<'T>. The first one takes a function 'T -> Something and performs comparison on the result. You can define a function like this:
/// Creates a comparer for 'T values based on a predicate that
/// selects some value 'U from any 'T value (e.g. a field)
let standardComparer (f:'T -> 'U) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
(f a).Equals(b) // Call 'f' on the value & test equality of results
member x.GetHashCode(a) =
(f a).GetHashCode() } // Call 'f' and get hash code of the result
The function is 'T -> 'U using F# generics, so you can project fields of any type (the type just has to be comparable). The second primitive function also takes 'T -> 'U, but it also takes a comparer for 'U values instead of using the default:
/// Creates a comparer for 'T values based on a predicate & comparer
let equalityComparer (f:'T -> 'U) (comparer:IEqualityComparer<'U>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comparer.Equals(f a, f b) // Project values using 'f' and use 'comparer'
member x.GetHashCode(a) =
comparer.GetHashCode(f a) } // Similar - use 'f' and 'comparer'
Now you're saying that you'd like to take a sequence of values created in one of the two above ways to build a single comparison strategy. I'm not entirely sure what you mean by that. Do you want two objects to be equal when all the specified comparers report them as equal?
Assuming that is the case, you can write a function that combines two IEqualityComparer<'T> values and reports them as equal when both comparers report them as equal like this:
/// Creates a new IEqualityComparer that is based on two other comparers
/// Two objects are equal if they are equal using both comparers.
let combineComparers (comp1:IEqualityComparer<'T>) (comp2:IEqualityComparer<'T>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comp1.Equals(a, b) && comp2.Equals(a, b) // Combine results using &&
member x.GetHashCode(a) =
// Get hash code of a tuple composed by two hash codes
hash (comp1.GetHashCode(a), comp2.GetHashCode(a)) }
This is essenitally implementing all the functionality that you need. If you have some object Person, you can construct comparer like this:
// Create a list of primitive comparers that compare
// Name, Age and ID using special 'idComparer'
let comparers =
[ standardComparer (fun (p:Person) -> p.Name);
standardComparer (fun (p:Person) -> p.Age);
equalityComparer (fun (p:Person) -> p.ID) idComparer ]
// Create a single comparer that combines all of them...
let comparePerson = comparers |> Seq.reduce combineComparers
You could wrap this in a more object-oriented interface using overloaded methods etc., but I think that the above sample shows all the important components that you'll need in the solution.
BTW: In the example, I was using F# object expressions to implement all the functions.

Parameterized Discriminated Union in F# [duplicate]

I am trying to write a typed abstract syntax tree datatype that can represent
function application.
So far I have
type Expr<'a> =
| Constant of 'a
| Application of Expr<'b -> 'a> * Expr<'b> // error: The type parameter 'b' is not defined
I don't think there is a way in F# to write something like 'for all b' on that last line - am I approaching this problem wrongly?
In general, the F# type system is not expressive enough to (directly) define a typed abstract syntax tree as the one in your example. This can be done using generalized algebraic data types (GADTs) which are not supported in F# (although they are available in Haskell and OCaml). It would be nice to have this in F#, but I think it makes the language a bit more complex.
Technically speaking, the compiler is complaining because the type variable 'b is not defined. But of course, if you define it, then you get type Expr<'a, 'b> which has a different meaning.
If you wanted to express this in F#, you'd have to use a workaround based on interfaces (an interface can have generic method, which give you a way to express constraint like exists 'b which you need here). This will probably get very ugly very soon, so I do not think it is a good approach, but it would look something like this:
// Represents an application that returns 'a but consists
// of an argument 'b and a function 'b -> 'a
type IApplication<'a> =
abstract Appl<'b> : Expr<'b -> 'a> * Expr<'b> -> unit
and Expr<'a> =
// Constant just stores a value...
| Constant of 'a
// An application is something that we can call with an
// implementation (handler). The function then calls the
// 'Appl' method of the handler we provide. As this method
// is generic, it will be called with an appropriate type
// argument 'b that represents the type of the argument.
| Application of (IApplication<'a> -> unit)
To represent an expression tree of (fun (n:int) -> string n) 42, you could write something like:
let expr =
Application(fun appl ->
appl.Appl(Constant(fun (n:int) -> string n),
Constant(42)))
A function to evaluate the expression can be written like this:
let rec eval<'T> : Expr<'T> -> 'T = function
| Constant(v) -> v // Just return the constant
| Application(f) ->
// We use a bit of dirty mutable state (to keep types simpler for now)
let res = ref None
// Call the function with a 'handler' that evaluates function application
f { new IApplication<'T> with
member x.Appl<'A>(efunc : Expr<'A -> 'T>, earg : Expr<'A>) =
// Here we get function 'efunc' and argument 'earg'
// The type 'A is the type of the argument (which can be
// anything, depending on the created AST)
let f = eval<'A -> 'T> efunc
let a = eval<'A> earg
res := Some <| (f a) }
res.Value.Value
As I said, this is a bit really extreme workaround, so I do not think it is a good idea to actually use it. I suppose the F# way of doing this would be to use untyped Expr type. Can you write a bit more about the overall goal of your project (perhaps there is another good approach)?

Typed abstract syntax tree with function application

I am trying to write a typed abstract syntax tree datatype that can represent
function application.
So far I have
type Expr<'a> =
| Constant of 'a
| Application of Expr<'b -> 'a> * Expr<'b> // error: The type parameter 'b' is not defined
I don't think there is a way in F# to write something like 'for all b' on that last line - am I approaching this problem wrongly?
In general, the F# type system is not expressive enough to (directly) define a typed abstract syntax tree as the one in your example. This can be done using generalized algebraic data types (GADTs) which are not supported in F# (although they are available in Haskell and OCaml). It would be nice to have this in F#, but I think it makes the language a bit more complex.
Technically speaking, the compiler is complaining because the type variable 'b is not defined. But of course, if you define it, then you get type Expr<'a, 'b> which has a different meaning.
If you wanted to express this in F#, you'd have to use a workaround based on interfaces (an interface can have generic method, which give you a way to express constraint like exists 'b which you need here). This will probably get very ugly very soon, so I do not think it is a good approach, but it would look something like this:
// Represents an application that returns 'a but consists
// of an argument 'b and a function 'b -> 'a
type IApplication<'a> =
abstract Appl<'b> : Expr<'b -> 'a> * Expr<'b> -> unit
and Expr<'a> =
// Constant just stores a value...
| Constant of 'a
// An application is something that we can call with an
// implementation (handler). The function then calls the
// 'Appl' method of the handler we provide. As this method
// is generic, it will be called with an appropriate type
// argument 'b that represents the type of the argument.
| Application of (IApplication<'a> -> unit)
To represent an expression tree of (fun (n:int) -> string n) 42, you could write something like:
let expr =
Application(fun appl ->
appl.Appl(Constant(fun (n:int) -> string n),
Constant(42)))
A function to evaluate the expression can be written like this:
let rec eval<'T> : Expr<'T> -> 'T = function
| Constant(v) -> v // Just return the constant
| Application(f) ->
// We use a bit of dirty mutable state (to keep types simpler for now)
let res = ref None
// Call the function with a 'handler' that evaluates function application
f { new IApplication<'T> with
member x.Appl<'A>(efunc : Expr<'A -> 'T>, earg : Expr<'A>) =
// Here we get function 'efunc' and argument 'earg'
// The type 'A is the type of the argument (which can be
// anything, depending on the created AST)
let f = eval<'A -> 'T> efunc
let a = eval<'A> earg
res := Some <| (f a) }
res.Value.Value
As I said, this is a bit really extreme workaround, so I do not think it is a good idea to actually use it. I suppose the F# way of doing this would be to use untyped Expr type. Can you write a bit more about the overall goal of your project (perhaps there is another good approach)?

Resources