I have a lot of modules that upon starting the program are supposed to add certain things to a single Dictionary found in a higher level module. However, it appears that expressions and constants within a module are packed into static constructors when compiling to a Console App, so these aren't evaluated unless explicitly referenced/when the program thinks they are needed.
There have been a few questions on here regarding initializing modules, and the consensus has been that it is not possible to force. However, I have not seen any of them explore reflection in this regard. In C# I know you are able to invoke the static constructor of a type, so I have attempted the same with F# modules.
My attempts have involved adding a custom attribute (MessageHandlerAttribute) to each module containing such an expression that I want evaluated upon starting the program, and then running this:
let initAllMessageHandlerModules =
Assembly.GetExecutingAssembly().GetTypes()
|> Array.choose (fun typ ->
typ.CustomAttributes
|> Seq.tryFind (fun attr -> attr.AttributeType = typeof<MessageHandlerAttribute>)
|> Option.map (fun _ -> typ))
|> Array.iter
(fun typ -> try typ.TypeInitializer.Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)
But this gives me the following error:
System.NullReferenceException: Object reference not set to an instance of an object.
I have also tried to swap the final lambda function with this:
(fun typ -> try System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typ.TypeHandle) |> ignore with | ex -> printfn "%A" ex)
But this appears to do nothing. Is it possible to achieve this?
Use type.GetConstructor instead of type.TypeInitializer.
(fun typ -> try typ.GetConstructor(BindingFlags.Instance ||| BindingFlags.Public, null, CallingConventions.Standard, Array.empty<Type>, Array.empty<ParameterModifier>).Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)
Here are some more examples
Related
Does Function Composition rely on Partial Application?
Here's my understanding:
Observe the following functions that have some duplication of function calls:
let updateCells (grid:Map<(int * int), Cell>) =
grid |> Map.toSeq
|> Seq.map snd
|> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
let mutable _cells = ObservableCollection<Cell>( grid |> Map.toSeq
|> Seq.map snd
|> Seq.toList )
let cycleHandler _ =
self.Cells <- ObservableCollection<Cell>( grid |> cycleThroughCells
|> Map.toSeq
|> Seq.map snd
|> Seq.toList )
If you’ve noticed, the following code appears in all three functions:
grid |> Map.toSeq
|> Seq.map snd
Function Composition
Within functional programming, we can fuse functions together so that they can become one function.
To do this, let’s create a new function from the duplicated sequence of functions:
let getCells = Map.toSeq >> Seq.map snd >> Seq.toList
Now if you’re attentive, you will have noticed that we don’t use any arguments when using Function Composition. Hence, the grid value is not used. The reason behind this is because of Partial Application.
Partial Application
I’m still learning all these functional programming techniques. However, my understanding is that partial application is a technique within functional programming that postpones the need to accept a complete set of arguments for a given function. In other words, partial application is the act of deferring the acceptance of a complete set of arguments for a given function in which there is an expectation that the end-client will provide the rest of the arguments later. At least, that’s my understanding.
We can now take a function like:
let updateCells (grid:Map<(int * int), Cell>) =
grid |> Map.toSeq
|> Seq.map snd
|> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
And refactor it to something like:
let updateCells (grid:Map<(int * int), Cell>) =
grid |> getCells
|> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
Are my thoughts regarding Function Composition being coupled with Partial Application accurate?
Generics
Actually, if you take the expression
let getCells = Map.toSeq >> Seq.map snd >> Seq.toList
and attempt to compile it as a stand-alone expression, you'll get a compiler error:
error FS0030: Value restriction. The value 'getCells' has been inferred to have generic type
val getCells : (Map<'_a,'_b> -> '_b list) when '_a : comparison
Either make the arguments to 'getCells' explicit or, if you do not intend for it to be generic, add a type annotation.
The reason it works in your case is because you're using the getCells function with grid, which means that the compiler infers it to have a constrained type.
In order to keep it generic, you can rephrase it using an explicit argument:
let getCells xs = xs |> Map.toSeq |> Seq.map snd |> Seq.toList
This expression is a valid stand-alone expression of the type Map<'a,'b> -> 'b list when 'a : comparison.
Point-free
The style used with the >> function composition operator is called point-free. It works well with partial application, but isn't quite the same.
Application
There is, however, an example of partial function application in this example:
let getCells xs = xs |> Map.toSeq |> Seq.map snd |> Seq.toList
The function snd has the following type:
'a * 'b -> 'b
It's function that takes a single argument.
You could also write the above getCells function without partial application of the snd function:
let getCells xs = xs |> Map.toSeq |> Seq.map (fun x -> snd x) |> Seq.toList
Notice that instead of a partially applied function passed to Seq.map, you can pass a lambda expression. The getCells function is still a function composed from other functions, but it no longer relies on partial application of snd.
Thus, to partially (pun intended) answer your question: function composition doesn't have to rely on partial function composition.
Currying
In F#, functions are curried by default. This means that all functions take exactly one argument, and returns a value. Sometimes (often), the return value is another function.
Consider, as an example, the Seq.map function. If you call it with one argument, the return value is another function:
Seq.map snd
This expression has the type seq<'a * 'b> -> seq<'b>, because the return value of Seq.map snd is another function.
Eta reduction
This means that you can perform an Eta reduction on the above lambda expression fun x -> snd x, because x appears on both sides of the expression. The result is simply snd, and the entire expression becomes
let getCells xs = xs |> Map.toSeq |> Seq.map snd |> Seq.toList
As you can see, partial application isn't necessary for function composition, but it does make it much easier.
Impartial
The above composition using the pipe operator (|>) still relies on partial application of the functions Map.toSeq, Seq.map, etcetera. In order to demonstrate that composition doesn't rely on partial application, here's an 'impartial' (the opposite of partial? (pun)) alternative:
let getCells xs =
xs
|> (fun xs' -> Map.toSeq xs')
|> (fun xs' -> Seq.map (fun x -> snd x) xs')
|> (fun xs' -> Seq.toList xs')
Notice that this version makes extensive use of lambda expressions instead of partial application.
I wouldn't compose functions in this way; I only included this alternative to demonstrate that it can be done.
Composition depends on first-class functions, not really on partial applications.
What is required to implement composition is that:
Functions must be able to be taken as arguments and returned as return values
Function signatures must be valid types (if you want the composition to be strongly-typed)
Partial application creates more opportunities for composition, but in principle you can easily define function composition without it.
For example, C# doesn't have partial application*, but you can still compose two functions together, as long as the signatures match:
Func<a, c> Compose<a, b, c>(this Func<a, b> f,
Func<b, c> g)
{
return x => g(f(x));
}
which is just >> with an uglier syntax: f.Compose(g).
However, there is one interesting connection between composition and partial application. The definition of the >> operator is:
let (>>) f g x = g(f(x))
and so, when you write foo >> bar, you are indeed partially applying the (>>) function, ie omitting the x argument to get the fun x = g(f(x)) partial result.
But, as I said above, this isn't strictly necessary. The Compose function above is equivalent to F#'s >> operator and doesn't involve any partial application; lambdas perform the same role in a slightly more verbose way.
* Unless you manually implement it, which nobody does. I.e. instead of writing
string foo(int a, int b)
{
return (a + b).ToString();
}
you'd have to write
Func<int, string> foo(int a)
{
return b => (a + b).ToString();
}
and then you'd be able to pass each argument separately just like in F#.
I have a code which looks like this:
this.GetItemTypeIdsAsListForOneItemTypeIdTreeUpIncludeItemType itemType.AutoincrementedId
|> Array.map (fun i -> i.AutoincrementedId)
|> Array.map (BusinessLogic.EntityTypes.getFullSetOfEntityTypeFieldValuesForItemTypeAid item.Autoincrementedid)
|> Array.fold Array.append [||]
|> Array.map (fun fv -> { fv with ReferenceAutoId = aid } )
|> Array.toSeq
|> Seq.distinctBy (fun fv -> fv.Fieldname)
|> Seq.toArray
Sometimes such code gets the unusual result which I need to explain. Usually there is not error in the code. There is an error in the data. And I need to explain why this backet of data is incorrect. What is the best way to do it ?
I just want to look at the list on each step of this expression.
Something like:
func data
|> func2 && Console.WriteLine
|> func3 && Console.WriteLine
....
Get input, split it on two. Pass one of the output to the next function, and second output to Console.
For a quick and dirty solution, you can always add a function like this one:
// ('a -> unit) -> 'a -> 'a
let tee f x = f x; x
If, for example, you have a composition like this:
[1..10]
|> List.map string
|> String.concat "|"
you can insert tee in order to achieve a side-effect:
[1..10]
|> List.map string
|> tee (printfn "%A")
|> String.concat "|"
That's not functional, but can be used in a pinch if you just need to look at some intermediate values; e.g. for troubleshooting.
Otherwise, for a 'proper' functional solution, perhaps application of the State monad might be appropriate. That will enable you to carry around state while performing the computation. The state could, for example, contain custom messages collected along the way...
If you just want to 'exit' as soon as you discover that something is wrong, though, then the Either monad is the appropriate way to go.
I keep running into the following problem:
(System.Console.ReadLine ()).Split [|'('; ')'|]
|> Array.filter (fun s -> not (System.String.IsNullOrEmpty (s)))
|> Array.map (fun s -> s.Split [|','|])
|> Array.map (fun s -> Array.map (fun t -> t.Trim ()) s) (* t.Trim () is underlined with a red squiggly line *)
|> [MORE CODE]
The error associated with the red squiggly line is:
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
But when the mouse pointer hovers over t, IntelliSense correctly says that t is of type string.
I can bypass the error by writing fun (t : string) -> [CODE], but I wonder why Visual Studio draws the squiggly line at all when it is already detecting the type of the variable correctly. Is this a simple bug in the trial build, or am I misunderstanding something about F#'s type inferencing?
Thanks in advance for your responses.
There is some gap between F# intellisense and F# type checker.
The type checker works from left to right in order. Your problem can be fixed be changing:
fun s -> Array.map (fun t -> t.Trim()) s
to
fun s -> s |> Array.map (fun t -> t.Trim())
Since type of s is available before using Array.map, the type checker is able to infer type of t.
Remarks:
This error usually occurs when using instance methods. You could replace these methods by static functions with extra type annotation and refactor to make your code more composable:
let split arr (s: string) = s.Split arr
let trim (s: string) = s.Trim()
System.Console.ReadLine()
|> split [|'('; ')'|]
|> Array.filter (not << System.String.IsNullOrEmpty)
|> Array.map (split [|','|])
|> Array.map (Array.map trim)
Let's take this code:
open System
open System.IO
let lines = seq {
use sr = new StreamReader(#"d:\a.h")
while not sr.EndOfStream do yield sr.ReadLine()
}
lines |> Seq.iter Console.WriteLine
Console.ReadLine()
Here I am reading all the lines in a seq, and to go over it, I am using Seq.iter. If I have a list I would be using List.iter, and if I have an array I would be using Array.iter. Isn't there a more generic traversal function I could use, instead of having to keep track of what kind of collection I have? For example, in Scala, I would just call a foreach and it would work regardless of the fact that I am using a List, an Array, or a Seq.
Am I doing it wrong?
You may or may not need to keep track of what type of collection you deal with, depending on your situation.
In case of simple iterating over items nothing may prevent you from using Seq.iter on lists or arrays in F#: it will work over arrays as well as over lists as both are also sequences, or IEnumerables from .NET standpoint. Using Array.iter over an array, or List.iter over a list would simply offer more effective implementations of traversal based on specific properties of each type of collection. As the signature of Seq.iter Seq.iter : ('T -> unit) -> seq<'T> -> unit shows you do not care about your type 'T after the traversal.
In other situations you may want to consider types of input and output arguments and use specialized functions, if you care about further composition. For example, if you need to filter a list and continue using result, then
List.filter : ('T -> bool) -> 'T list -> 'T list will preserve you the type of underlying collection intact, but Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T> being applied to a list will return you a sequence, not a list anymore:
let alist = [1;2;3;4] |> List.filter (fun x -> x%2 = 0) // alist is still a list
let aseq = [1;2;3;4] |> Seq.filter (fun x -> x%2 = 0) // aseq is not a list anymore
Seq.iter works on lists and arrays just as well.
The type seq is actually an alias for the interface IEnumerable<'T>, which list and array both implement. So, as BLUEPIXY indicated, you can use Seq.* functions on arrays or lists.
A less functional-looking way would be the following:
for x in [1..10] do
printfn "%A" x
List and Array is treated as Seq.
let printAll seqData =
seqData |> Seq.iter (printfn "%A")
Console.ReadLine() |> ignore
printAll lines
printAll [1..10]
printAll [|1..10|]
how does one convert from a list of characters to a string?
To put it another way, how do I reverse List.ofSeq "abcd"?
UPDATE: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" seems to work fine, with or without new, but List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" fails. Why?
I asked a similar question once before. It seems object constructors aren't composable so you can't pass them as a function.
List.ofSeq "abcd" |> List.toArray |> (fun s -> System.String s) |> printfn "%A"
List.ofSeq "abcd" |> List.toArray |> (fun s -> new System.String(s)) |> printfn "%A"
Update
Constructors are first-class functions as of F# 4.0
List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A"
Working with strings in F# is sometimes a bit uncomfortable. I would probably use the same code as Dario. The F# grammar doesn't allow using constructors as first class functions, so you unfortunately cannot do the whole processing in a single pipeline. In general, you can use static members and instance methods as first class functions, but not instance properties or constructors.
Anyway, there is a really nasty trick you can use to turn a constructor into a function value. I would not recommend actually using it, but I was quite surprised to see that it actually works, so I thought it may be worth sharing it:
let inline ctor< ^R, ^T
when ^R : (static member ``.ctor`` : ^T -> ^R)> (arg:^T) =
(^R : (static member ``.ctor`` : ^T -> ^R) arg)
This defines a function that will be inlined at compile time, which requires that the first type parameter has a constructor that takes a value of the second type parameter. This is specified as a compile-time constraint (because .NET generics cannot express this). Also, F# doesn't allow you to specify this using the usual syntax for specifying constructor constraints (which must take unit as the argument), but you can use the compiled name of constructors. Now you can write for example:
// just like 'new System.Random(10)'
let rnd = ctor<System.Random, _> 10
rnd.Next(10)
And you can also use the result of ctor as first-class function:
let chars = [ 'a'; 'b'; 'c' ]
let str = chars |> Array.ofSeq |> ctor<System.String, _>
As I said, I think this is mainly a curiosity, but a pretty interesting one :-).
Your approach:
new System.String (listOfChars |> List.toArray)
is the solution I usually end up with too.
F#'s grammar/type inference system simply seems unable to recognize a .NET constructor like new String as a curried function (which prevents you from using pipelining).
Just faced similar problem, and came up with this solutions:
List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd")