Refactoring F# while-do "mutable" code into functional "immutable" code - functional-programming

I have been trying to re-write one of my simple C# console app into purely functional F# code (if at all possible). Up until now I have managed to re-write while blocks into "immutable" F# with the help of Seq (something like Seq.initInfinite sequenceGenerator |> Seq.takeWhile condition |> Seq.iter bodyOfWhileCycle) - the website "F# for Fun and Profit" has been my inspiration. However, this time I came across a simple while block that in "mutable" F# looks like follows (and it works):
printfn "Type low OP number"
let mutable lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let mutable highLimit = parseMe (Console.ReadLine())
let mutable myCondition = true
if highLimit > lowLimit then myCondition <- false
while myCondition do
printfn "Type low OP number again"
lowLimit <- parseMe (Console.ReadLine())
printfn "Type high OP number again"
highLimit <- parseMe (Console.ReadLine())
if highLimit > lowLimit then myCondition <- false
Can anyone help me to figure out how to refactor this "mutable" while-do block into a functional style? My attempts to refactor it do not work the way I want - I do not know how to get the lowLimit1/highLimit1 values out of the bodyOfWhileCycle function. One of my unsuccessfull attempts is here:
printfn "Type low OP number"
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let highLimit = parseMe (Console.ReadLine())
let verifyingInputValues: unit =
let bodyOfWhileCycle _=
printfn "Type low OP number again"
let lowLimit1 = parseMe (Console.ReadLine())
printfn "Type high OP number again"
let highLimit1 = parseMe (Console.ReadLine())
()
fun _ -> highLimit - lowLimit
|> Seq.initInfinite
|> Seq.takeWhile ((>) 0)
|> Seq.iter bodyOfWhileCycle
verifyingInputValues

It looks like you want to have the while loop finish when highLimit > lowLimit and otherwise repeat requests, and presumably, do something with them later.
In which case you want a function that returns a tuple of ( highLimit, lowLimit ) and not unit (). A recursive function can handle the apparent change in state or IO between calls, without mutability, by passing the new state in as an argument.
let fullParse: () -> int *int =
let parseHighLow again =
printfn "Type low OP number %s" again
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number %s" again
let highLimit = parseMe (Console.ReadLine())
highLimit, lowLimit
let rec verify (high, low) =
if high > low then high, low else verify (parseHighLow "again")
verify (parseHighLow "")
let (high, low) = fullParse ()

Take notice of the skip rather than take because we are waiting for what we want to be received from a user. What we want is one thing so we apply the head function to the sequence. Overall your attempt was close but your sequence wasn't producing values.
open System
let rec p name =
printfn "Input %s Value" name
let text = Console.ReadLine()
let (ok, i) = Int32.TryParse text
if ok then i else p name
let ps () =
Seq.initInfinite (fun _ -> p "High", p "Low")
|> Seq.skipWhile (fun (high, low) -> high <= low)
|> Seq.head
let (high, low) = ps ()

Related

OCaml guessing number game

I've decided to do a simple exercise in OCaml, writing a guess the number application:
The solution I came up with was this:
let () =
let func_end = ref false in
while !func_end != true do
let () = print_endline "Enter guess:" in
let input = read_int () in
let bound = 50 in
let random_number = Random.int bound in
if input == random_number then
let () = print_endline "Correct!" in
func_end := true
done
I wonder if there's a more functional approach to this problem,
the use of refs seems more imperative rather than functional.
You have a while loop and a ref type, which are imperative features of OCaml, rather than functional, but you can approximate the functionality of this loop in a generalized functional way with recursion.
A while loop involves an initial state, a boolean predicate, and a body. We can pass these things to a function, with the predicate being a function which tests the state, and the body working on the state to generate a new state.
let rec do_while state pred body =
if pred state then
let state = body state in
do_while state pred body
else
state
Consider a simple example of this:
utop # do_while 1 (fun x -> x < 10) (fun x -> Printf.printf "%d\n" x; x + 1);;
1
2
3
4
5
6
7
8
9
- : int = 10
It can then be used to replace your loop. The state will be the correct number, and the guess. Of course, the guess won't exist on the first go around so we'll use a value of type int option. If the correct number and the guess are the same, the function will return true and the loop will end. Otherwise it will continue. The loop body function will prompt for input and update the state. It will also print an error message if the guess isn't correct.
let _ =
do_while
(Random.int 50, None)
(function
| (correct, Some guess) when correct = guess -> false
| _ -> true)
(fun (correct, _) ->
let () = print_endline "guess a number:" in
let guess = read_int () in
(if correct <> guess then print_endline "Incorrect guess!";
(correct, Some guess)))
As an aside, you do not need the ref type in your while loop. You can use an exception to exit the loop.
exception Exit
try
while true do
let () = print_endline "Enter guess:" in
let input = read_int () in
let bound = 50 in
let random_number = Random.int bound in
if input = random_number then raise Exit
done
with
| Exit -> ()
The "functional loop" is recursion.
A good step would be to split this into functions; something like this, perhaps
let guess () =
let () = print_endline "Enter guess: " in
read_int()
let answer () =
Random.int 50
let rec play () =
if guess () = answer () then
print_endline "Correct!"
else
play ()
But I personally feel that it's a bit unfair to create a new correct answer for every guess, so you might want to stick to just one
let guess () =
let () = print_endline "Enter guess: " in
read_int()
let answer () =
Random.int 50
let play () =
let rec with_guess it =
if guess () = it then
print_endline "Correct!"
else
with_guess it
in
with_guess ## answer ()
This can easily be extended to provide hints, such as "too high" or "too low".

Accidental recursion, blowing up the stack with Seq.append, without using `rec`

I had code that was waiting to blow up something lurking around. Using F# 4.1 Result it is similar to this:
module Result =
let unwindSeq (sourceSeq: #seq<Result<_, _>>) =
sourceSeq
|> Seq.fold (fun state res ->
match state with
| Error e -> Error e
| Ok innerResult ->
match res with
| Ok suc ->
Seq.singleton suc
|> Seq.append innerResult
|> Ok
| Error e -> Error e) (Ok Seq.empty)
The obvious bottleneck here is Seq.singleton added to Seq.append. I understand that this is slow (and badly written), but why does it have to blow up the stack? I don't think that Seq.append is inherently recursive...
// blows up stack, StackOverflowException
Seq.init 1000000 Result.Ok
|> Result.unwindSeq
|> printfn "%A"
And as an aside, to unwind a sequence of Result, I fixed this function by using a simple try-catch-reraise, but that feels sub-par too. Any ideas as to how to do this more idiomatically without force-evaluating the sequence or blowing up the stack?
Not-so-perfect unwinding (it also forces the result-fail type), but at least without pre-evaluation of the sequence:
let unwindSeqWith throwArgument (sourceSeq: #seq<Result<_, 'a -> 'b>>) =
try
sourceSeq
|> Seq.map (throwOrReturnWith throwArgument)
|> Ok
with
| e ->
(fun _ -> raise e)
|> Error
I believe the idiomatic way of folding a sequence of Results in the way you suggest would be:
let unwindSeq<'a,'b> =
Seq.fold<Result<'a,'b>, Result<'a seq, 'b>>
(fun acc cur -> acc |> Result.bind (fun a -> cur |> Result.bind (Seq.singleton >> Seq.append a >> Ok)))
(Ok Seq.empty)
Not that this will be any faster than your current implementation, it just leverages Result.bind to do most of the work. I believe the stack is overflowing because a recursive function somewhere in the F# library, likely in the Seq module. My best evidence for this is that materializing the sequence to a List first seems to make it work, as in the following example:
let results =
Seq.init 2000000 (fun i -> if i <= 1000000 then Result.Ok i else Error "too big")
|> Seq.toList
results
|> unwindSeq
|> printfn "%A"
However, this may not work in your production scenario if the sequence is too big to materialize in memory.

F# implicit typing choking on simple recursion

When I define a recursive function in F# thus:
let rec recursiveSum inputs =
let startState = 0.0m
if List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
...all is good. When I attempt to avoid the "empty list" problem thus:
let rec recursiveSum inputs =
let startState = 0.0m
**if List.isEmpty inputs then startState**
if List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
...I get yelled at:
recursion.fsx(5,9): error FS0001: This expression was expected to have type
unit
but here has type
decimal
What am I missing here?
From the docs:
The types of the values produced in each branch must match. If there is no explicit else branch, its type is unit. Therefore, if the type of the then branch is any type other than unit, there must be an else branch with the same return type.
You're missing said else.
let rec recursiveSum inputs =
let startState = 0.0m
if List.isEmpty inputs then 0.0m
elif List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
(N.b. I've used elif here rather than nesting another if expression; hopefully that's not too much of a distraction.)
That said, your logic involving startState is highly suspect; it's always zero, and really serves no purpose here. Your state should probably be a parameter rather than a local value so it can be used as an accumulator:
let recursiveSum inputs =
let rec impl state inputs =
if List.isEmpty inputs then state
elif List.length inputs = 1 then
state + inputs.Head
else
let t = List.tail inputs
impl (state + inputs.Head) t
impl 0.0m inputs
Lastly, let's make it idiomatic:
let recursiveSum inputs =
let rec impl state inputs =
match inputs with
| [] -> state
| [h] -> state + h
| h::t -> impl (state + h) t
impl 0.0m inputs
which can be shortened to
let recursiveSum inputs =
let rec impl state = function
| [] -> state
| h::t -> impl (state + h) t
impl 0.0m inputs
With ildjarns answer, I think I would suggest that one could/should go all the way...
let rec fold f acc = function
| [] -> acc
| [x] -> f x acc
| h::t -> fold f (f h acc) t
let someDec = [0.1m; 0.2m]
let someStr = ["world"; "Hello "]
someDec
|> fold (+) 0.0m
someStr
|> fold (+) ""
let recursiveSum = fold (+) 0.0m
someDec
|> recursiveSum
let recursiveStrAdd = fold (+) ""
someStr
|> recursiveStrAdd
someDec
|> recursiveSum
(And I never remember left or right here, so... ;-)

F# stop Seq.map when a predicate evaluates true

I'm currently generating a sequence in a similar way to:
migrators
|> Seq.map (fun m -> m())
The migrator function is ultimately returning a discriminated union like:
type MigratorResult =
| Success of string * TimeSpan
| Error of string * Exception
I want to stop the map once I encounter my first Error but I need to include the Error in the final sequence.
I have something like the following to display a final message to the user
match results |> List.rev with
| [] -> "No results equals no migrators"
| head :: _ ->
match head with
| Success (dt, t) -> "All migrators succeeded"
| Error (dt, ex) -> "Migration halted owing to error"
So I need:
A way to stop the mapping when one of the map steps produces an Error
A way to have that error be the final element added to the sequence
I appreciate there may be a different sequence method other than map that will do this, I'm new to F# and searching online hasn't yielded anything as yet!
I guess there are multiple approaches here, but one way would be to use unfold:
migrators
|> Seq.unfold (fun ms ->
match ms with
| m :: tl ->
match m () with
| Success res -> Some (Success res, tl)
| Error res -> Some (Error res, [])
| [] -> None)
|> List.ofSeq
Note the List.ofSeq at the end, that's just there for realizing the sequence. A different way to go would be to use sequence comprehensions, some might say it results in a clearer code.
The ugly things Tomaš alludes to are 1) mutable state, and 2) manipulation of the underlying enumerator. A higher-order function which returns up to and including when the predicate holds would then look like this:
module Seq =
let takeUntil pred (xs : _ seq) = seq{
use en = xs.GetEnumerator()
let flag = ref true
while !flag && en.MoveNext() do
flag := not <| pred en.Current
yield en.Current }
seq{1..10} |> Seq.takeUntil (fun x -> x % 5 = 0)
|> Seq.toList
// val it : int list = [1; 2; 3; 4; 5]
For your specific application, you'd map the cases of the DU to a boolean.
(migrators : seq<MigratorResult>)
|> Seq.takeUntil (function Success _ -> false | Error _ -> true)
I think the answer from #scrwtp is probably the nicest way to do this if your input is reasonably small (and you can turn it into an F# list to use pattern matching). I'll add one more version, which works when your input is just a sequence and you do not want to turn it into a list.
Essentially, you want to do something that's almost like Seq.takeWhile, but it gives you one additional item at the end (the one, for which the predicate fails).
To use a simpler example, the following returns all numbers from a sequence until one that is divisible by 5:
let nums = [ 2 .. 10 ]
nums
|> Seq.map (fun m -> m % 5)
|> Seq.takeWhile (fun n -> n <> 0)
So, you basically just need to look one element ahead - to do this, you could use Seq.pairwise which gives you the current and the next element in the sequence"
nums
|> Seq.map (fun m -> m % 5)
|> Seq.pairwise // Get sequence of pairs with the next value
|> Seq.takeWhile (fun (p, n) -> p <> 0) // Look at the next value for test
|> Seq.mapi (fun i (p, n) -> // For the first item, we return both
if i = 0 then [p;n] else [n]) // for all other, we return the second
|> Seq.concat
The only ugly thing here is that you then need to flatten the sequence again using mapi and concat.
This is not very nice, so a good thing to do would be to define your own higher-order function like Seq.takeUntilAfter that encapsulates the behavior you need (and hides all the ugly things). Then your code could just use the function and look nice & readable (and you can experiment with other ways of implementing this).

How do I use the F# Reflection library?

I am trying to follow this example (from p137 of Rob Pickering's "Foundations of F#" book) but I can't get it to work with the latest F# CTP.
I appear to be missing the definition of 'Value' on the 3rd line where it does
Value.GetInfo(x)
This generates :
error FS0039: The namespace or module 'Value' is not defined.
Can anyone tell me where this is coming from or what the new syntax is if this is now done differently? (be gentle - this is my first play with F#)
Here's the example I am working from:-
#light
open Microsoft.FSharp.Reflection
let printTupleValues x =
match Value.GetInfo(x) with
| TupleValue vals ->
print_string "("
vals
|> List.iteri
(fun i v ->
if i <> List.length vals - 1 then
Printf.printf " %s, " (any_to_string v)
else
print_any v)
print_string " )"
| _ -> print_string "not a tuple"
printTupleValues ("hello world", 1)
The F# reflection library was rewritten for either Beta 1 or the CTP. Here is your code slightly changed to use the new library, and to avoid using the F# PlusPack (print_string is for OCaml compatibility).
open Microsoft.FSharp.Reflection
let printTupleValues x =
if FSharpType.IsTuple( x.GetType() ) then
let s =
FSharpValue.GetTupleFields( x )
|> Array.map (fun a -> a.ToString())
|> Array.reduce (fun a b -> sprintf "%s, %s" a b)
printfn "(%s)" s
else
printfn "not a tuple"
printTupleValues ("hello world", 1)
Or, if you prefer using match to decompose the tuple, then try this using an active pattern. Advantage is you can add support for additional types pretty easily.
open Microsoft.FSharp.Reflection
let (|ParseTuple|_|) = function
| o when FSharpType.IsTuple( o.GetType() ) ->
Some( FSharpValue.GetTupleFields(o) )
| _ -> None
let printTupleValues = function
| ParseTuple vals ->
let s =
vals
|> Array.map (fun a -> a.ToString())
|> Array.reduce (fun a b -> sprintf "%s, %s" a b)
printfn "(%s)" s
| _ ->
printf "not a tuple"
printTupleValues ("hello world", 1)
I don't know whether your function has been renamed or removed in the current F# versions.
You should take a look at FSharp.Reflection in your IDE's object explorer to check that and maybe read this page.

Resources