In my F# application I often need to perform a case-insensitive search of a string within a string, so I created a function with the appropriate comparison:
let indexOf (str:string) (value:string) startIndex =
match str.IndexOf(value, startIndex, StringComparison.OrdinalIgnoreCase) with
| index when index >= 0 -> Some index
| _ -> None
I do not like the fact, that when I want to search from the beginning, I have to pass the redundant 0 as the start index.
I am relatively new to both F# and the functional programming, so I would like to know what is the preferred (cleanest) solution from the functional point of view?
Create two versions:
let indexOfFrom (str:string) (value:string) startIndex = (...)
let indexOf str value = indexOfFrom str value 0
Use Option type:
let foundIndex = indexOf "bar foobar" "bar" (Some 4)
Create a dedicated discriminated union:
type Position =
| Beginning
| StartIndex of index : int
let foundIndex = indexOf "bar foobar" "bar" (Index 4)
Place the 'indexOf' function inside a type and use the 'classic' overloading.
Place the 'indexOf' function inside a type and use F# optional arguments.
If you are defining the functionality as F# functions, then I think that using two separate functions (with reasonably descriptive names) is probably the best option you have. So I'd go with your first option (I definitely prefer this option over defining a discriminated union just for this single purpose):
let indexOfFrom (str:string) (value:string) startIndex = (...)
let indexOf str value = indexOfFrom str value 0
The alternative is to define the functionality as members of a type - then you can use both overloading and F# optional arguments, but you'd have to access them using full name String.IndexOf. You could write something like:
type String =
static member IndexOf(str:string, value:string, startIndex) = (...)
static member IndexOf(str, value) = String.IndexOf(str, value, 0)
Or, using optional parameters:
type String =
static member IndexOf(str:string, value:string, ?startIndex) = (...)
Which of the options is the best one?
If you're designing functional API (e.g. domain-specific language), then your option with two separate functions is probably the best choice.
If you're aiming to design a nice F# API, then I think your option (multiple functions) or optional parameters are quite reasonable. Functions are used quite heavily in Deedle and F# Charting relies on optional arguments.
The benefit of using overloading is that the library will be also nicely usable from C#. So, if you're thinking of calling the library from C#, this is pretty much the only option.
I think option 1 (with curried function) would be simplest. Curried functions are pretty common in functional programming.
In options 2 or 3 you'll still have to pass additional parameter to the function for the search from the beginning
Options 4 or 5 require additional overhead to create type. It's kind of 'overkill' for this simple task
Related
I am trying to understand the following code, particularly StringConstant:
type StringConstant = StringConstant of string * string
[<EntryPoint>]
let main argv =
let x = StringConstant("little", "shack")
printfn "%A" x
0 // return an integer exit code
(By way of context, StringConstant is used in the FParsec tutorial, but this example does not use FParsec.)
What I would like to know is:
what exactly is the type statement doing?
once I instantiate x, how would I access the individual "parts"
("little" or "house")
As others already noted, technically, StringConstant is a discriminated union with just a single case and you can extract the value using pattern matching.
When talking about domain modelling in F#, I like to use another useful analogy. Often, you can start just by saying that some data type is a tuple:
type Person = string * int
This is really easy way to represent data, but the problem is that when you write "Tomas", 42, the compiler does not know that you mean Person, but instead understands it as string * int tuple. One-case discriminated unions are a really nice way to name your tuple:
type Person = Person of string * int
It might be a bit confusing that this is using the name Person twice - first as a type name and second as a name of the case. This has no special meaning - it simply means that the type will have the same name as the case.
Now you can write Person("Tomas", 42) to create a value and it will have a type Person. You can decompose it using match or let, but you can also easily write functions that take Person. For example, to return name, you can write:
let getName (Person(name, _)) =
name
I think single-case discriminated unions are often used mainly because they are really easy to define and really easy to work with. However, I would not use them in code that is exposed as a public API because they are a bit unusual and may be confusing.
PS: Also note that you need to use parentheses when extracting the values:
// Correct. Defines symbols 'name' and 'age'
let (Person(name, age)) = tomas
// Incorrect! Defines a function `Person` that takes a tuple
// (and hides the `Person` case of the discriminated union)
let Person(name, age) = tomas
StringConstant is a discriminated union type, with just a single case (also named StringConstant). You extract the parts via pattern matching, using match/function or even just let, since there is just a single case:
let (StringConstant(firstPart, secondPart)) = x
type StringConstant = StringConstant of string * string
results in a discriminated union with one type.
type StringConstant = | StringConstant of string * string if you execute it in F# interactive.
You can see the msdn documentation on that here.
You can get the value out like this:
let printValue opt =
match opt with
| StringConstant( x, y) -> printfn "%A%A" x y
The other guys already mentioned how you extract the data from a discriminated union, but to elaborate a little more on Discriminated unions one could say that they are sorta like enums on steroids. They are implemented behind the scenes as a type hierarchy where the type is the base class and the cases are subclases of that baseclass with whatever parameter they might have as readonly public variables.
In Scala a similar data-structure is called case classes which might help you convince yourself of this implementationmethod.
One nice property of discriminated unions are that they are self-referenceable and therefor are perfect for defining recursive structures like a tree. Below is a definition of a Hoffman coding tree in just three lines of code. Doing that in C# would probably take somewhere between 5 and 10 times as many lines of code.
type CodeTree =
| Branch of CodeTree * CodeTree * list<char> * int
| Leaf of char * int
For information about Discriminated Unions see the msdn documentation
For an example of using Discriminated Unions as a tree-structure see this gist which is an implementation of a huffman decoder in roughly 60 lines of F#)
Say, I have
member this.Test (x: 'a) = printfn "generic"
1
member this.Test (x: Object) = printfn "non generic"
2
If I call it in C#
var a = test.Test(3); // calls generic version
var b = test.Test((object)3); // calls non generic version
var c = test.Test<object>(3); // calls generic version
However, in F#
let d = test.Test(3); // calls non generic version
let e = test.Test<int>(3); // calls generic version
So I have to add type annotation so as to get the correct overloaded method. Is this true? If so, then why F# doesn't automatically resolve correctly given that the argument type is already inferred? (what is the order of F#'s overload resolution anyway? always favor Object than its inherited classes?)
It is a bit dangerous if a method has both overloads, one of them takes argument as Object type and the other one is generic and both return the same type. (like in this example, or Assert.AreEqual in unit testing), as then it is very much likely we get the wrong overloading without even notice (won't be any compiler error). Wouldn't it be a problem?
Update:
Could someone explain
Why F# resolves Assert.AreEqual(3, 5) as Assert.AreEqual(Object a, Object b) but not Assert.AreEqual<T>(T a, T b)
But F# resolves Array.BinarySearch([|2;3|], 2) as BinarySearch<T>(T[]array, T value) but not BinarySearch(Array array, Object value)
F# Method overload resolution not as smart as C#?
I don't think it's true. Method overloading makes type inference much more difficult. F# has reasonable trade-offs to make method overloading usable and type inference as powerful as it should be.
When you pass a value to a function/method, F# compiler automatically upcasts it to an appropriate type. This is handy in many situations but also confusing sometimes.
In your example, 3 is upcasted to obj type. Both methods are applicable but the simpler (non-generic) method is chosen.
Section 14.4 Method Application Resolution in the spec specifies overloading rules quite clearly:
1) Prefer candidates whose use does not constrain the use of a
user-introduced generic type annotation to be equal to another type.
2) Prefer candidates that do not use ParamArray conversion. If two
candidates both use ParamArray conversion with types pty1 and pty2,
and pty1 feasibly subsumes pty2, prefer the second; that is, use the
candidate that has the more precise type.
3) Prefer candidates that do not have
ImplicitlyReturnedFormalArgs.
4) Prefer candidates that do not have
ImplicitlySuppliedFormalArgs.
5) If two candidates have unnamed actual argument types ty11...ty1n and ty21...ty2n, and each ty1i either
a. feasibly subsumes ty2i, or
b. ty2i is a System.Func type and ty1i is some other delegate
type, then prefer the second candidate. That is, prefer any candidate that has the more specific actual argument types, and
consider any System.Func type to be more specific than any other
delegate type.
6) Prefer candidates that are not extension members over
candidates that are.
7) To choose between two extension members, prefer the one that
results from the most recent use of open.
8) Prefer candidates that are not generic over candidates that are
generic—that is, prefer candidates that have empty ActualArgTypes.
I think it's users' responsibility to create unambiguous overloaded methods. You can always look at inferred types to see whether you're doing them correctly. For example, a modified version of yours without ambiguity:
type T() =
member this.Test (x: 'a) = printfn "generic"; 1
member this.Test (x: System.ValueType) = printfn "non-generic"; 2
let t = T()
let d = t.Test(3) // calls non-generic version
let e = t.Test(test) // call generic version
UPDATE:
It comes down a core concept, covariance. F# doesn't support covariance on arrays, lists, functions, etc. It's generally a good thing to ensure type safety (see this example).
So it's easy to explain why Array.BinarySearch([|2;3|], 2) is resolved to BinarySearch<T>(T[] array, T value). Here is another example on function arguments where
T.Test((fun () -> 2), 2)
is resolved to
T.Test(f: unit -> 'a, v: 'a)
but not to
T.Test(f: unit -> obj, v: obj)
Are there any documents or examples out there on how one can extend/add new keywords to query expressions? Is this even possible?
For example, I'd like to add a lead/lag operator.
In addition to the query builder for the Rx Framework mentioned by #pad, there is also a talk by Wonseok Chae from the F# team about Computation Expressions that includes query expressions. I'm not sure if the meeting was recorded, but there are very detailed slides with a cool example on query syntax for generating .NET IL code.
The source code of the standard F# query builder is probably the best resource for finding out what types of operations are supported and how to annotate them with attributes.
The key attributes that you'll probably need are demonstrated by the where clause:
[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where :
: source:QuerySource<'T,'Q> *
[<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
The CustomOperation attribute defines the name of the operation. The (quite important) parameter MaintainsVariableSpace allows you to say that the operation returns the same type of values as it takes as the input. In that case, the variables defined earlier are still available after the operation. For example:
query { for p in db.Products do
let name = p.ProductName
where (p.UnitPrice.Value > 100.0M)
select name }
Here, the variables p and name are still accessible after where because where only filters the input, but it does not transform the values in the list.
Finally, the ProjectionParameter allows you to say that p.UnitValue > 100.0M should actually be turned into a function that takes the context (available variables) and evaluates this expression. If you do not specify this attribute, then the operation just gets the value of the argument as in:
query { for p in .. do
take 10 }
Here, the argument 10 is just a simple expression that cannot use values in p.
Pretty cool feature for the language. Just implemented the reverse to query QuerySource.
Simple example, but just a demonstration.
module QueryExtensions
type ExtendedQueryBuilder() =
inherit Linq.QueryBuilder()
/// Defines an operation 'reverse' that reverses the sequence
[<CustomOperation("reverse", MaintainsVariableSpace = true)>]
member __.Reverse (source : Linq.QuerySource<'T,System.Collections.IEnumerable>) =
let reversed = source.Source |> List.ofSeq |> List.rev
new Linq.QuerySource<'T,System.Collections.IEnumerable>(reversed)
let query = ExtendedQueryBuilder()
And now it being used.
let a = [1 .. 100]
let specialReverse =
query {
for i in a do
select i
reverse
}
I thought that I might be able to do this with quotations - but I can't see how.
Should I just use a table of the functions with their names - or is their a way of doing this?
Thanks.
For more info......
I'm calling a lot of f# functions from excel and I wondered if I could write a f# function
let fs_wrapper (f_name:string) (f_params:list double) =
this bit calls fname with f_params
and then use
=fs_wrapper("my_func", 3.14, 2.71)
in the sheet rather than wrap all the functions separately.
You'll need to use standard .NET Reflection to do this. Quotations aren't going to help, because they represent function calls using standard .NET MethodInfo, so you'll need to use reflection anyway. The only benefit of quotations (compared to naive reflection) is that you can compile them, which could give you better performance (but the compilation isn't perfect).
Depending on your specific scenario (e.g. where are the functions located), you'd have to do something like:
module Functions =
let sin x = sin(x)
let sqrt y = sqrt(y)
open System.Reflection
let moduleInfo =
Assembly.GetExecutingAssembly().GetTypes()
|> Seq.find (fun t -> t.Name = "Functions")
let name = "sin"
moduleInfo.GetMethod(name).Invoke(null, [| box 3.1415 |])
Unless you need some extensibility or have a large number of functions, using a dictionary containing string as a key and function value as the value may be an easier option:
let funcs =
dict [ "sin", Functions.sin;
"sqrt", Functions.sqrt ]
funcs.[name](3.1415)
There are many methods but one way is to use Reflection, for instance:
typeof<int>.GetMethod("ToString", System.Type.EmptyTypes).Invoke(1, null)
typeof<int>.GetMethod("Parse", [|typeof<string>|]).Invoke(null, [|"112"|])
GetMethod optionally takes an array of types that define the signature, but you can skip that if your method is unambiguous.
Following up on what Thomas alluded to, have a look at Using and Abusing the F# Dynamic Lookup Operator by Matthew Podwysocki. It offers a syntactically clean way for doing dynamic lookup in F#.
when using .net classes, there are cases when we don't need parenthesis to pass a single parameter like
let foo = DirectoryInfo "boo"
but something a little more complicated using a single parameter, we do need parenthesis...
does anyone know the parsing rules when this is true?
In F#, all functions take a single parameter. Now this may be a little confusing at first, because you can have a function which appears to take more than one parameter, but you're actually passing a single parameter that is a tuple.
Here's a simple example of constructors that appear like they take more than 1 parameter:
let foo = DirectoryInfo "boo" //passing 1 argument
let foo2 = DirectoryInfo ("boo") //passing 1 argument that is a tuple
let foo3 = StringBuilder ("blah", 100) //passing 1 argument again
let foo4 = StringBuilder "blah" 100 //does not compile
For more info about this style, check out Tuples on MSDN.
Now, there also is another slightly different method of making it seem like a function takes more than 1 argument. This is called currying, which you will see more often when dealing only with F# code. Here's a quick example of this.