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".
Related
I'm trying to write some code in a functional paradigm for practice. There is one case I'm having some problems wrapping my head around. I am trying to create an array of 5 unique integers from 1, 100. I have been able to solve this without using functional programming:
let uniqueArray = [];
while (uniqueArray.length< 5) {
const newNumber = getRandom1to100();
if (uniqueArray.indexOf(newNumber) < 0) {
uniqueArray.push(newNumber)
}
}
I have access to lodash so I can use that. I was thinking along the lines of:
const uniqueArray = [
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100()
].map((currentVal, index, array) => {
return array.indexOf(currentVal) > -1 ? getRandom1to100 : currentVal;
});
But this obviously wouldn't work because it will always return true because the index is going to be in the array (with more work I could remove that defect) but more importantly it doesn't check for a second time that all values are unique. However, I'm not quite sure how to functionaly mimic a while loop.
Here's an example in OCaml, the key point is that you use accumulators and recursion.
let make () =
Random.self_init ();
let rec make_list prev current max accum =
let number = Random.int 100 in
if current = max then accum
else begin
if number <> prev
then (number + prev) :: make_list number (current + 1) max accum
else accum
end
in
make_list 0 0 5 [] |> Array.of_list
This won't guarantee that the array will be unique, since its only checking by the previous. You could fix that by hiding a hashtable in the closure between make and make_list and doing a constant time lookup.
Here is a stream-based Python approach.
Python's version of a lazy stream is a generator. They can be produced in various ways, including by something which looks like a function definition but uses the key word yield rather than return. For example:
import random
def randNums(a,b):
while True:
yield random.randint(a,b)
Normally generators are used in for-loops but this last generator has an infinite loop hence would hang if you try to iterate over it. Instead, you can use the built-in function next() to get the next item in the string. It is convenient to write a function which works something like Haskell's take:
def take(n,stream):
items = []
for i in range(n):
try:
items.append(next(stream))
except StopIteration:
return items
return items
In Python StopIteration is raised when a generator is exhausted. If this happens before n items, this code just returns however much has been generated, so perhaps I should call it takeAtMost. If you ditch the error-handling then it will crash if there are not enough items -- which maybe you want. In any event, this is used like:
>>> s = randNums(1,10)
>>> take(5,s)
[6, 6, 8, 7, 2]
of course, this allows for repeats.
To make things unique (and to do so in a functional way) we can write a function which takes a stream as input and returns a stream consisting of unique items as output:
def unique(stream):
def f(s):
items = set()
while True:
try:
x = next(s)
if not x in items:
items.add(x)
yield x
except StopIteration:
raise StopIteration
return f(stream)
this creates an stream in a closure that contains a set which can keep track of items that have been seen, only yielding items which are unique. Here I am passing on any StopIteration exception. If the underlying generator has no more elements then there are no more unique elements. I am not 100% sure if I need to explicitly pass on the exception -- (it might happen automatically) but it seems clean to do so.
Used like this:
>>> take(5,unique(randNums(1,10)))
[7, 2, 5, 1, 6]
take(10,unique(randNums(1,10))) will yield a random permutation of 1-10. take(11,unique(randNums(1,10))) will never terminate.
This is a very good question. It's actually quite common. It's even sometimes asked as an interview question.
Here's my solution to generating 5 integers from 0 to 100.
let rec take lst n =
if n = 0 then []
else
match lst with
| [] -> []
| x :: xs -> x :: take xs (n-1)
let shuffle d =
let nd = List.map (fun c -> (Random.bits (), c)) d in
let sond = List.sort compare nd in
List.map snd sond
let rec range a b =
if a >= b then []
else a :: range (a+1) b;;
let _ =
print_endline
(String.concat "\t" ("5 random integers:" :: List.map string_of_int (take (shuffle (range 0 101)) 5)))
How's this:
const addUnique = (ar) => {
const el = getRandom1to100();
return ar.includes(el) ? ar : ar.concat([el])
}
const uniqueArray = (numberOfElements, baseArray) => {
if (numberOfElements < baseArray.length) throw 'invalid input'
return baseArray.length === numberOfElements ? baseArray : uniqueArray(numberOfElements, addUnique(baseArray))
}
const myArray = uniqueArray(5, [])
Attempting to find anagrams in a list of words using F Sharps Async Sequences (I am aware there are better algorithms for anagram finding but trying to understand Async Sequneces)
From the 'runTest' below how can I
1. async read the collecion returned and output to screen
2. block until all results return & display final count/collection
open System
open System.ServiceModel
open System.Collections.Generic
open Microsoft.FSharp.Linq
open FSharp.Control
[<Literal>]
let testWord = "table"
let testWords = new List<string>()
testWords.Add("bleat")
testWords.Add("blate")
testWords.Add("junk")
let hasWord (word:string) =
let mutable res = true
let a = testWord.ToCharArray() |> Set.ofArray
let b = word.ToCharArray() |> Set.ofArray
let difference = Set.intersect a b
match difference.Count with
| 0 -> false
| _ -> true
let test2 (words:List<string>, (word:string)) : AsyncSeq<string> =
asyncSeq {
let res =
(words)
|> Seq.filter(fun x-> (hasWord(x)) )
|> AsyncSeq.ofSeq
yield! res
}
let runTest = test2(testWords,testWord)
|> //pull stuff from stream
|> // output to screen
|> ignore
()
So as you have the test2 function returning an asyncSeq. Your questions:
1. async read the collecion returned and output to screen
If you want to have some side-effecting code (such as outputting to the screen) you can use AsyncSeq.iter to apply a function to each item as it becomes available. Iter returns an Async<unit> so you can then "kick it off" using an appropriate Async method (blocking/non-blocking).
For example:
let processItem i =
// Do whatever side effecting code you want to do with an item
printfn "Item is '%s'" i
let runTestQ1 =
test2 (testWords, testWord)
|> AsyncSeq.iter processItem
|> Async.RunSynchronously
2. block until all results return & display final count/collection
If you want all the results collected so that you can work on them together, then you can convert the AsyncSeq into a normal Seq using AsyncSeq.toBlockingSeq and then convert it to a list to force the Seq to evaluate.
For example:
let runTestQ2 =
let allResults =
test2 (testWords, testWord)
|> AsyncSeq.toBlockingSeq
|> Seq.toList
// Do whatever you would like with your list of results
printfn "Final list is '%A' with a count of %i" allResults (allResults.Length)
Say i want to return an Option while in an async workflow:
let run =
async {
let! x = doAsyncThing
let! y = doNextAsyncThing x
match y with
| None -> return None
| Some z -> return Some <| f z
}
Ideally I would use the maybe computation expression from FSharpx at the same time as async to avoid doing the match. I could make a custom builder, but is there a way to generically combine two computation expressions? It might look something like this:
let run =
async {
let! x = doAsyncThing
let! y = doNextAsyncThing x
return! f y
}
Typically in F# instead of using generic workflows you define the workflow by hand, or use one that is ready available as in your case async and maybe but if you want to use them combined you will need to code a specific workflow combination by hand.
Alternatively you can use F#+ which is a project that provides generic workflows for monads, in that case it will be automatically derived for you, here's a working example, using your workflow and then using OptionT which is a monad transformer:
#r "nuget: FSharpPlus, 1.2"
open FSharpPlus
open FSharpPlus.Data
let doAsyncThing = async {return System.DateTime.Now}
let doNextAsyncThing (x:System.DateTime) = async {
let m = x.Millisecond
return (if m < 500 then Some m else None)}
let f x = 2 * x
// then you can use Async<_> (same as your code)
let run = monad {
let! x = doAsyncThing
let! y = doNextAsyncThing x
match y with
| None -> return None
| Some z -> return Some <| f z}
let res = Async.RunSynchronously run
// or you can use OptionT<Async<_>> (monad transformer)
let run' = monad {
let! x = lift doAsyncThing
let! y = OptionT (doNextAsyncThing x)
return f y}
let res' = run' |> OptionT.run |> Async.RunSynchronously
The first function has to be 'lifted' into the other monad, because it only deals with Async (not with Option), the second function deals with both so it only needs to be 'packed' into our OptionT DU.
As you can see both workflows are derived automatically, the one you had (the async workflow) and the one you want.
For more information about this approach read about Monad Transformers.
A simple way to do so is to use Option module:
let run =
async {
let! x = doAsyncThing
let! y = doNextAsyncThing x
return Option.map f y
}
I suppose you don't have to deal with option in context of async so often. FSharpx also provides many more high-order functions for option type. Most of the cases, I think using them is enough.
To get the feeling of using these functions, please take a look at this nice article.
type MaybeMonad() =
member __.Bind(x, f) =
match x with
| Some v -> f v
| None -> None
member __.Return(x) =
Some x
let maybe = MaybeMonad()
let run = async {
let! x = doAsyncThing
let! y = doNextAsyncThing x
return maybe {
let! y_val = y
return f y_val
}
}
just use f# Computation expressions inside.
I have written some state machine in C++ and Java but never in a functional language like Ocaml
Problem is I don't know if I can just adapt code from the object languages versions, since in Ocaml records and variants are more powerful than class;
So, I need an event-driven finite state machine (hierarchical like in UML), easily configurable
Could someone experienced in the field post a simple sample of that ? Just to avoid the most common traps
thanks :)
EDIT 16/03 : Is it possible to do it without mutable state ?
And I'd like to encapsulate it properly under the name "FSM", should I choose a module or a class ?
It depends on how you have to operate the FSM, e.g., if you need to be able to store its state and continue later, or if you just want to execute it immediately. In the latter case, it's trivial to do it as a bunch of tail-recursive functions.
For example, assume the regexp C((A|B)*CD)* -- the following mutually recursive functions are a direct implementation of the respective FSM that recognises a list matching this regexp (if I didn't make any mistake :) ):
type alphabet = A | B | C | D
let rec s1 = function
| C :: rest -> s2 rest
| _ -> false
and s2 = function
| [] -> true
| (A | B) :: rest -> s2 rest
| C :: rest -> s3 rest
| _ -> false
and s3 = function
| D :: rest -> s2 rest
| _ -> false
Every function corresponds to exactly one state of the automaton and implements its transition function. Applying s1 : alphabet list -> bool will run the FSM on the argument.
PS: Note how this is an application demonstrating the benefit and elegance of tail call optimization...
Usually, you create a record corresponding to a state of the automata, and you have another type for the event triggering the transition to another state. In the state record, you have a map to find, for each event, the new state.
Let's suppose your transitions are triggered by strings:
type event = string
module EventMap = Map.Make(struct
type t = event
let compare = compare
end)
type state = {
state_info : ...; (* the content of that state, id, comment, etc. *)
mutable state_transitions : state EventMap.t;
}
let next_state current_state event =
try
EventMap.find event current_state.state_transitions
with Not_found -> current_state
Here, I supposed that unknown events stay on the same state, but you could have an error state in the record...
There is an excellent answer which demonstrates expressiveness and elegance of OCaml in representing finite state machine here:
automata in ocaml
For more serious use, you could try to look at some finite state machine library like fsm library here.
I recently created an FSM module in OCaml which you can find here
I have some special requirements for my FSM implementation which could make it not quite as nice to look at as some of the others pointed out here, however, I think the way you declare the FSM itself is kind of nice and declarative. The special requirement is that I need to be able to generate code in HDL (hardware description language) from a declarative description of the FSM in addition to being able to simulate the FSM's operation in the OCaml version. Because of this I needed to use predicate expressions instead of transition functions (otherwise, how would I translate a function to a string?) So mainly you want to focus on the FSM module there and the create and eval_fsm functions there.
Here is an example of usage:
(*********************************************************
* FSM testing *******************************************
*)
(* inputs to the FSM *)
let full = Var({name ="full"; value = F});;
let ten_minutes = Var({name = "ten_minutes"; value = F});;
let empty = Var({name = "empty"; value = F});;
let five_minutes = Var({name = "five_minutes"; value =F});;
(* T is true, F is false *)
let _ =
assign full F ;
assign ten_minutes F ;
assign empty F ;
assign five_minutes F ;;
(* outputs from the FSM *)
let water_on = Var({name = "water_on"; value = F});;
let agitate = Var({name = "agitate"; value = F});;
let drain = Var({name = "drain" ; value = F});;
let start_timer = Var({name = "start_timer"; value = F});;
let motor_on = Var({name = "motor_on"; value = F});;
let washed = Var({name = "washed"; value = F});;
let soap = Var({name = "soap"; value = F});;
let reset_actions =
assign water_on F;
assign agitate F;
assign drain F;
assign start_timer F;
assign motor_on F;;
module WashStates =
struct
type t = START | FILL | WASH | DRAIN | RINSE | SPIN | STOP
deriving(Show, Enum)
let start_state = START
end
module LogicExp =
struct
type t = boolean Logic.bexp
type var_t = boolean Logic.variable
let eval_exp exp = to_bool (Logic.eval exp)
let var_to_s = var_to_s
end
module WashFSM = FSM(WashStates)(LogicExp)
open WashStates
(* declare the state table *)
(* CS, PREDICATE, NS, ACTIONs *)
let my_fsm = [
(START, Const(T), FILL, [(water_on, T);
(soap, T)]);
(FILL, Bop(And,full,soap), WASH, [(water_on, F);
(agitate, T);
(washed, T);
(start_timer,T)]);
(WASH, ten_minutes, DRAIN,[(agitate, F);
(start_timer,F);
(empty, T)]);
(DRAIN, Bop(And,empty,soap), FILL, [(drain, F);
(soap, F);
(water_on, T)] );
(FILL, Bop(And,full,Not(soap)), RINSE,[(water_on, F);
(soap, F);
(empty, F);
(agitate, T)]);
(RINSE, ten_minutes, DRAIN, [(agitate, F);
(empty, T)] );
(DRAIN, Bop(And,empty,Not(soap)), SPIN, [(motor_on, T);
(start_timer,T)]);
(SPIN, five_minutes, STOP, [(water_on, F);
(drain, F);
(start_timer,F);
(motor_on, F)]);
(STOP, Const(T), STOP, [(motor_on, F)]);
];;
let st_table, current_state = WashFSM.create my_fsm in
let _ = assign full T in
let current_state = WashFSM.eval_fsm st_table current_state in
let _ = assign ten_minutes T in
let current_state = WashFSM.eval_fsm st_table current_state in
let current_state = WashFSM.eval_fsm st_table current_state in
let _ = (assign ten_minutes F);(assign empty T) in
let current_state = WashFSM.eval_fsm st_table current_state in
let _ = assign five_minutes T in
let current_state = WashFSM.eval_fsm st_table current_state in
let _ = assign five_minutes F in
let _ = assign ten_minutes T in
let current_state = WashFSM.eval_fsm st_table current_state in
let current_state = WashFSM.eval_fsm st_table current_state in
let _ = assign five_minutes T in
let _ = WashFSM.eval_fsm st_table current_state in
(*...and so on...*)
(Please excuse the ";;" endings - I wanted to be able to cut & paste this code into the REPL)
Some of the code used here is found in the Logic project on my github (fsm.ml is part of that project). The predicate expression evaluates to either T or F (true or false). If true, then the transition is made from current state to next state. Const T means always transition. An expression such as:
Bop(And, full, soap)
Means that if both full and soap are T (true) then the expression evaluates to true.
For an assignment, i have written the following code in recursion. It takes a list of a vector data type, and a vector and calculates to closeness of the two vectors. This method works fine, but i don't know how to do the recursive version.
let romulus_iter (x:vector list) (vec:vector) =
let vector_close_hash = Hashtbl.create 10 in
let prevkey = ref 10000.0 in (* Define previous key to be a large value since we intially want to set closefactor to prev key*)
if List.length x = 0 then
{a=0.;b=0.}
else
begin
Hashtbl.clear vector_close_hash;
for i = 0 to (List.length x)-1 do
let vecinquestion = {a=(List.nth x i).a;b=(List.nth x i).b} in
let closefactor = vec_close vecinquestion vec in
if (closefactor < !prevkey) then
begin
prevkey := closefactor;
Hashtbl.add vector_close_hash closefactor vecinquestion
end
done;
Hashtbl.find vector_close_hash !prevkey
end;;
The general recursive equivalent of
for i = 0 to (List.length x)-1 do
f (List.nth x i)
done
is this:
let rec loop = function
| x::xs -> f x; loop xs
| [] -> ()
Note that just like a for-loop, this function only returns unit, though you can define a similar recursive function that returns a meaningful value (and in fact that's what most do). You can also use List.iter, which is meant just for this situation where you're applying an impure function that doesn't return anything meaningful to each item in the list:
List.iter f x