F#: any way to use member functions as unbound functions? - f#

Is there a way to extract member functions, and use them as F# functions? I'd like to be able to write the following:
mystring |> string.Split '\n' |> Array.filter (string.Length >> (=) 0 >> not)
The code above works if you [let]
let mystring = "a c\nb\n"
let stringSplit (y:char) (x:string) = x.Split(y)
let stringLength (x:string) = x.Length
mystring |> stringSplit '\n' |> Array.filter (stringLength >> (=) 0 >> not)

This is quite similar to a question I asked a few days ago (but your wording is better). The consensus seems to be:
No.
Maybe the syntax string#Split, "foo"#Split, or just #Split (type-inferred) will be added in the future. But Don Syme's proposal that Tomas linked to was from 2007, so I don't know how likely it is to happen--probably about as likely as a specific syntax for laziness, I'd guess.
Edit:
I guess "foo"#Split could also be written as string#Split "foo". I guess it depends how flexibly you define the # syntax.

Use
(fun x -> x.Member ...)
for now. For example
someString |> (fun s -> s.Split "\n") |> ...

Related

Using bind and Kliesli composition operators with Result

I'm trying to use the bind (>>=) and Kleisli composition (>=>) operators with the basic Result type, but either they are not defined or are not in scope:
let f x =
if x%2 = 0 then Ok (x/2)
else Error ()
let ff x = Ok x >>= f >>= f
let ff' = f >=> f
[<EntryPoint>]
let main _ =
printfn "%A" (ff 12)
printfn "%A" (ff' 28)
0
Error FS0043 Expecting a type supporting the operator '>>=' but given a function type. You may be missing an argument to a function.
I've tried to open a few different namespaces to bring the definition into scope, but no luck.
It seems from this like the operators can't be defined in general without extensions, but are there definitions for the standard Result anywhere?
Haskell-like operators are not defined in the F# core library, nor are they likely to ever be. You'll need to either write them in your own prelude, or use a library like FSharpPlus for these and other more Haskell-like (Well, typelevel) programming approaches.
In addition to what Phillip said in his answer, it might be useful to add that you can rewrite your example using the built-in Result.bind operation and function composition or piping:
let f x =
if x%2 = 0 then Ok (x/2)
else Error ()
let ff x = Ok x |> Result.bind f |> Result.bind f
let ff' = f >> Result.bind f
printfn "%A" (ff 12)
printfn "%A" (ff' 28)
This is of course just a toy example, so it's hard to say what you actually want to do, but if I was trying to use Result, my first choice would be to use the standard library functions - they may make your code longer, but it is arguably more readable.

Is it possible to define an F# operator that applies multiple functions to a single argument (almost the opposite of the ||> operator)?

My attempt to do this is here (forgive the for loop - I was just curious to see if this was possible):
let (|>>) a (b : ('a -> unit) list) =
for x in b do
x a
but when I try to use it I get the error
That None of the types error message can occur if the function you're trying to use is defined further down the file or isn't imported correctly. Otherwise, your function definition seems ok.
I would discourage the use of a custom operator for this. I think they should be used very rarely. This one doesn't seem general enough to be worth defining and could make code hard to read. Here is one alternative:
[ printf "%A"; printfn "%A" ] |> List.iter ((|>) 1)
But it's even clearer and shorter to write out your operator definition inline:
for f in [ printf "%A"; printfn "%A" ] do f 1

Is there a built-in F# function to perform a side-effect on an item and return the item [duplicate]

...or in FSharpx?
let tee sideEffect =
fun x ->
do sideEffect x
x
The usage could be something like
f >> tee (printfn "F returned: %A") >> g >> h
Or is there another simple way to do this?
thanks!
The closest I've seen is actually in WebSharper. The definition is:
let inline ( |>! ) x sideEffect =
do sideEffect x
x
Usage:
(x |>! printf "%A") |> nextFunc
ExtCore includes a function called tap which does exactly what you want. I use it for primarily for inspecting intermediate values within an F# "pipeline" (hence the name).
For example:
[| 1;2;3 |]
|> Array.map (fun x -> x * 2)
|> tap (fun arr ->
printfn "The mapped array values are: %A" arr)
|> doOtherStuffWithArray
As far as I know, a function like this isn't defined anywhere in the F# core library - though the library is missing many standard functions that are quite easy to define yourself, so my recommendation would be just to add it somewhere in your project - your tee seems like the best way to go.
That said, I'd probably prefer using less declarative style if I need side-effects and write something like:
let fResult = f fInput
printfn "F returned: %A" fResult
fResult |> g |> h
This is just a matter of style, but I prefer declarative style for fully declarative code and imperative style when there are side-effects involved. As a bonus, using local variables makes debugging easier. But using a function like tee is an equally good alternative that many people in the F# community would prefer.

Avoid mutation in this example in F#

Coming from an OO background, I am having trouble wrapping my head around how to solve simple issues with FP when trying to avoid mutation.
let mutable run = true
let player1List = ["he"; "ho"; "ha"]
let addValue lst value =
value :: lst
while run do
let input = Console.ReadLine()
addValue player1List input |> printfn "%A"
if player1List.Length > 5 then
run <- false
printfn "all done" // daz never gunna happen
I know it is ok to use mutation in certain cases, but I am trying to train myself to avoid mutation as the default. With that said, can someone please show me an example of the above w/o using mutation in F#?
The final result should be that player1List continues to grow until the length of items are 6, then exit and print 'all done'
The easiest way is to use recursion
open System
let rec makelist l =
match l |> List.length with
|6 -> printfn "all done"; l
| _ -> makelist ((Console.ReadLine())::l)
makelist []
I also removed some the addValue function as it is far more idiomatic to just use :: in typical F# code.
Your original code also has a common problem for new F# coders that you use run = false when you wanted run <- false. In F#, = is always for comparison. The compiler does actually warn about this.
As others already explained, you can rewrite imperative loops using recursion. This is useful because it is an approach that always works and is quite fundamental to functional programming.
Alternatively, F# provides a rich set of library functions for working with collections, which can actually nicely express the logic that you need. So, you could write something like:
let player1List = ["he"; "ho"; "ha"]
let player2List = Seq.initInfinite (fun _ -> Console.ReadLine())
let listOf6 = Seq.append player1List list2 |> Seq.take 6 |> List.ofSeq
The idea here is that you create an infinite lazy sequence that reads inputs from the console, append it at the end of your initial player1List and then take first 6 elements.
Depending on what your actual logic is, you might do this a bit differently, but the nice thing is that this is probably closer to the logic that you want to implement...
In F#, we use recursion to do loop. However, if you know how many times you need to iterate, you could use F# List.fold like this to hide the recursion implementation.
[1..6] |> List.fold (fun acc _ -> Console.ReadLine()::acc) []
I would remove the pipe from match for readability but use it in the last expression to avoid extra brackets:
open System
let rec makelist l =
match List.length l with
| 6 -> printfn "all done"; l
| _ -> Console.ReadLine()::l |> makelist
makelist []

Convert a list of characters (or array) to a string

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")

Resources