I want to go from:
let a = fun x ->
x
|> f
|> g
to something like this:
let a = |> f
|> g
I tried:
let a = (<|) f
|> g
and similars
let a = fun x -> x |> f |> g
is equivalent to
let a x = x |> f |> g
It looks like you want to compose two functions f and g to create a new function a. You can use the >> operator to compose functions. You could write:
let a = f >> g
If f and g are generic functions then it will fail to compile due to F# value restrictions. In that case, you need to add type annotations:
let a<'a> : ('a -> 'a) = f >> g
Related
I have declared the following operator to help make my curried code a bit more legible
Pipe-Through allows a value to be passed through a method and continue out the other side. I think it helps make my code more succinct.
let (|>!) x f = x |> f |> ignore; x
Example of use
let y = x |> transform
y |> logger.LogInformation
y
|> process
|> return
Now becomes
x
|> transform
|>! logger.LogInformation
|> process
|> return
Is this useful or have I reinvented the wheel
It is useful and like all good inventions it has been independently made by others as well.
Scott Wlaschin called it tee: https://fsharpforfunandprofit.com/rop/
The proposed operator is |>!:
let inline tee f v = f v ; v
let inline (|>!) v f = f v ; v
let inline (>>!) g f = g >> fun v -> f v ; v /// composition
(5 * 8) |> tee (printfn "value = %d") |> doSomethingElse
(5 * 8) |>! printfn "value = %d" |> doSomethingElse
This definition is slightly different than yours as it does not use ignore.
Thanks for sharing!
I'm trying to explore the dynamic capabilities of F# for situations where I can't express some function with the static type system. As such, I'm trying to create a mapN function for (say) Option types, but I'm having trouble creating a function with a dynamic number of arguments. I've tried:
let mapN<'output> (f : obj) args =
let rec mapN' (state:obj) (args' : (obj option) list) =
match args' with
| Some x :: xs -> mapN' ((state :?> obj -> obj) x) xs
| None _ :: _ -> None
| [] -> state :?> 'output option
mapN' f args
let toObjOption (x : #obj option) =
Option.map (fun x -> x :> obj) x
let a = Some 5
let b = Some "hi"
let c = Some true
let ans = mapN<string> (fun x y z -> sprintf "%i %s %A" x y z) [a |> toObjOption; b |> toObjOption; c |> toObjOption]
(which takes the function passed in and applies one argument at a time) which compiles, but then at runtime I get the following:
System.InvalidCastException: Unable to cast object of type 'ans#47' to type
'Microsoft.FSharp.Core.FSharpFunc`2[System.Object,System.Object]'.
I realize that it would be more idiomatic to either create a computation expression for options, or to define map2 through map5 or so, but I specifically want to explore the dynamic capabilities of F# to see whether something like this would be possible.
Is this just a concept that can't be done in F#, or is there an approach that I'm missing?
I think you would only be able to take that approach with reflection.
However, there are other ways to solve the overall problem without having to go dynamic or use the other static options you mentioned. You can get a lot of the same convenience using Option.apply, which you need to define yourself (or take from a library). This code is stolen and adapted from F# for fun and profit:
module Option =
let apply fOpt xOpt =
match fOpt,xOpt with
| Some f, Some x -> Some (f x)
| _ -> None
let resultOption =
let (<*>) = Option.apply
Some (fun x y z -> sprintf "%i %s %A" x y z)
<*> Some 5
<*> Some "hi"
<*> Some true
To explain why your approach does not work, the problem is that you cannot cast a function of type int -> int (represented as FSharpFunc<int, int>) to a value of type obj -> obj (represented as FSharpFunc<obj, obj>). The types are the same generic types, but the cast fails because the generic parameters are different.
If you insert a lot of boxing and unboxing, then your function actually works, but this is probably not something you want to write:
let ans = mapN<string> (fun (x:obj) -> box (fun (y:obj) -> box (fun (z:obj) ->
box (Some(sprintf "%i %s %A" (unbox x) (unbox y) (unbox z))))))
[a |> toObjOption; b |> toObjOption; c |> toObjOption]
If you wanted to explore more options possible thanks to dynamic hacks - then you can probably do more using F# reflection. I would not typically use this in production (simple is better - I'd just define multiple map functions by hand or something like that), but the following runs:
let rec mapN<'R> f args =
match args with
| [] -> unbox<'R> f
| x::xs ->
let m = f.GetType().GetMethods() |> Seq.find (fun m ->
m.Name = "Invoke" && m.GetParameters().Length = 1)
mapN<'R> (m.Invoke(f, [| x |])) xs
mapN<obj> (fun a b c -> sprintf "%d %s %A" a b c) [box 1; box "hi"; box true]
[<ReflectedDefinition>]
module Foo =
let x = 5
let y () = 6
let z a = a
I tried to find out how to get the AST in this situation a couple of times now and keep failing. Time to ask the question here.
So far, I thought that a module would be mappped to a class with static members internally and as such, it should be the equivalent of:
[<ReflectedDefinition>]
type Foo =
static member x = 5
static member y () = 6
static member z a = a
let bar_members =
typeof<Bar>.GetMethods()
|> Array.filter (fun mi -> match mi with | MethodWithReflectedDefinition x -> true | _ -> false)
|> Array.map (fun m -> sprintf "%s: %A" (m.Name) (Expr.TryGetReflectedDefinition(m :> MethodBase) ) )
In the latter case, I could use typeof<Foo>.GetMembers() (or GetMethods()?!), cast it to Reflection.MethodBase and use this as an argument for Expr.TryGetReflectedDefinition().
But unfortunately, this is not working with the module version.
So, how to do it?
If you want to play with the code, you might want to open some namespaces:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open System.Reflection
The problem comes go down to actually getting the type of the Module. In order to do that, there's a great answer here by Phillip Trelford: https://stackoverflow.com/a/14706890/5438433
Basically, you add a helper value to your module which returns the type of that module:
[<ReflectedDefinition>]
module Foo =
type internal IMarker = interface end
let fooType = typeof<IMarker>.DeclaringType
let x = 5
let y () = 6
let z a = a
You can then use fooType to retrieve the reflected definitions.
let foo_members =
Foo.fooType.GetMethods()
|> Array.filter (fun mi -> match mi with | MethodWithReflectedDefinition x -> true | _ -> false)
|> Array.map (fun m -> sprintf "%s: %A" (m.Name) (Expr.TryGetReflectedDefinition(m :> MethodBase) ) )
I can then, e.g. print the results:
[|"get_fooType: Some PropertyGet (Some (Call (None, TypeOf, [])), DeclaringType, [])";
"get_x: Some Value (5)";
"y: Some Lambda (unitVar0, Value (6))";
"z: Some Lambda (a, a)"|]
For the use case, when the reflected definitions are in another assembly (like an F# dll, for example), you can do without the marker interface trick, as shown below:
open System
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open System.Reflection
open FSharp.Reflection.FSharpReflectionExtensions
let tryGetReflectedModules (a : Assembly) : seq<TypeInfo> =
a.DefinedTypes
|> Seq.filter
(fun dt ->
dt.CustomAttributes
|> Seq.map (fun cad -> cad.AttributeType)
|> Seq.filter ((=) (typeof<ReflectedDefinitionAttribute>))
|> Seq.isEmpty
|> not
)
let astFromReflectedDefinition (mi : MethodInfo) : Expr option =
mi :> MethodBase |> Expr.TryGetReflectedDefinition
let reflectedMethodsOfAModule (m : System.Type) : (MethodInfo * Expr) [] =
m.GetMethods()
|> Array.map (fun m -> (m,astFromReflectedDefinition m))
|> Array.filter (snd >> Option.isSome)
|> Array.map (fun (x,y) -> (x, Option.get y))
let reflectAssembly (assemblyPath : string) =
let a = System.Reflection.Assembly.LoadFile(assemblyPath)
a
|> tryGetReflectedModules
|> Seq.map (fun x -> (x,reflectedMethodsOfAModule (x.AsType())))
Where, for example, the assembly I used for testing the code above looked like this:
namespace Input
[<ReflectedDefinition>]
module Api =
let trace s =
for _ in [0..3] do System.Diagnostics.Trace.WriteLine s
[<ReflectedDefinition>]
module Foo =
let foobar (x : string) : string =
x.ToUpper()
You get the top level types in the assembly, which just so happen to be the (static) classes, representing the modules of the Fsharp assembly and test for the ReflectedDefinitionAttribute presence. Then, you take it from there.
I'm new to F# and have a question about functions pipeline. Let's say we have a function map which maps list of functions to array of values creating a list of arrays:
//val map : ('a -> 'b) list -> 'a [] -> 'b [] list
let map funcs vals =
funcs |> List.map (fun f -> Array.map f vals)
Usage example:
//val it : float [] list = [[|1.0; 1.144729886|]; [|15.15426224; 23.14069263|]]
map [log; exp] [|Math.E; Math.PI|]
Is there a way to replace lambda function (fun f -> Array.map f vals) with a chain of pipeline operators?
I'd like to write smth like:
//val map : 'a [] list -> ('a -> 'b) -> 'b [] list
let map funcs vals = funcs |> List.map (vals |> Array.map)
But this doesn't work.
Many thanks,
Ivan
You can use this one.
let map funcs vals = funcs |> List.map (Array.map >> ((|>) vals))
The part Array.map >> ((|>) vals) partially applies f to Array.map and then composes it with the application of vals.
To me, the most readable cross-product function would be:
let flip f y x = f x y // a pretty standard function for flipping arguments of function
let crossProduct funcs vals =
(<|)
>> flip Array.map vals
|> flip List.map funcs
let result = crossProduct [log; exp] [|Math.E; Math.PI|]
TL;DR: A bit of explanation.
The pattern: xs |> List.map f is very popular, but sometimes it is better to write:
f |> List.map <| xs
Or, using flip: f |> flip List.map xs
Considering this, let's write the function in the most straightforward way:
let cartesianProduct0 funcs vals =
fun f ->
fun v -> f v
|> (flip Array.map vals)
|> (flip List.map funcs)
Then you notice that fun v -> f v is actually (<):
fun f ->
((<|) f)
|> (flip Array.map vals)
or:
fun f ->
f
|> (<|)
|> (flip Array.map vals)
or, simply:
(<|)
>> flip Array.map vals
The rest you need to do is just a minor style refactoring.
Is it possible to locally restrict the import of a module, preferrably combining this with Module Abbreviations? The goal is to avoid polluting my current module with symbols from imports.
e.g. (inspired by OCaml) something like that:
let numOfEvenIntegersSquaredGreaterThan n =
let module A = Microsoft.FSharp.Collections.Array in
[|1..100|] |> A.filter (fun x -> x % 2 = 0)
|> A.map (fun x -> x * x)
|> A.filter (fun x -> x > n)
|> A.length
let elementsGreaterThan n =
let module A = Microsoft.FSharp.Collections.List in
[1..100] |> A.filter (fun x -> x > n)
Additionally is there a way to achieve something similar with namespaces?
The goal is to avoid polluting my
current module with symbols from
imports.
Note that open Array is not allowed in F# (contrary to OCaml).
You can use abbreviations on modules, but only in the global scope:
module A = Microsoft.FSharp.Collections.Array
Instead of Microsoft.FSharp.Collections.Array, you can use Array. So your code would be:
let numOfEvenIntegersSquaredGreaterThan n =
[|1..100|] |> Array.filter (fun x -> x % 2 = 0)
|> Array.map (fun x -> x * x)
|> Array.filter (fun x -> x > n)
|> Array.length
If you want to reuse the same code for Arrays and Lists, you might want to use the Seq module:
let elementsGreaterThan n =
[1..100] |> Seq.filter (fun x -> x > n)