I'm trying out OOP in F# and have run in to a problem. I'm trying to build a drone and an airspace class, but for some reason my printDrones function does not work so I have no way to check if the rest of it even works. I don't get any errors, but the function just doesn't print anything out. I think I might have some problems with my types or list functions but I've tried so many things now I'm about to give up. Hopefully someone here can help me out!
type Drone(startposition: (float * float), destination: (float * float), speed: float) =
let mutable position = startposition
let a = fst destination - fst position
let b = snd destination - snd position
let c = sqrt(a**2.0 + b**2.0)
let speeddir = (a/c, b/c)
member this.fly =
position <- (fst position + (fst speeddir * speed), snd position + (snd speeddir * speed))
member this.getPos = position
member this.isFinished =
(fst startposition - fst destination)*(fst position - fst destination) < 0.0
type Airspace() =
let mutable drones: Drone List = []
member this.droneDist (d1: Drone) (d2: Drone) : float =
let d1pos = d1.getPos
let d2pos = d2.getPos
let a = fst d1pos - fst d2pos
let b = snd d1pos - snd d2pos
sqrt(a**2.0+ b**2.0)
member this.flyDrones() =
drones |> List.iter (fun x -> x.fly)
member this.addDrone(dr: Drone) =
drones <- dr :: drones
member this.printDrones() =
drones |> List.iter (fun x -> printfn "%A" (x.getPos))
let aspace = Airspace()
aspace.addDrone(Drone((50.0,100.0),(0.0,0.0), 20.0))
aspace.addDrone(Drone((0.0,100.0),(0.0,0.0), 20.0))
aspace.addDrone(Drone((25.0,100.0),(0.0,0.0), 20.0))
aspace.addDrone(Drone((75.0,100.0),(0.0,0.0), 20.0))
aspace.flyDrones
aspace.printDrones
Related
When declaring a function, I've 3 different ways:
let f x = ...
let f = (fun x -> ...)
let f = function
| ... -> (pattern matching)
It's this last one that I don't fully understand how it works.
I was doing a function that, considering a list (we'll assume it has integers in it but could be anything), reverses it, pretty basic, but with a complexity of O(n). After struggling for an hour at least I check the answer, and it is written like this:
let reverse lst =
let rec aux acc = function
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
I thought that using the key word function was just another way of doing patter matching, but when I do this:
let reverse lst =
let rec aux acc =
match aux with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
It doesn't work, and idk why. On top of that, why can we add tl at the end of the first function? Isn't aux a single argument function?
There are a few problems with this question. First, the code you give as the solution for reverse is not valid OCaml. It matches aux (which is a function) against list patterns. Most likely aux was supposed to be acc. But even so it doesn't seem right because it should have two arguments (the accumulated result and the input that still needs to be processed).
Second, your two code examples are the same. You seem to be saying that one works and one doesn't work. That doesn't make sense since they're the same.
IMHO you need to rewrite the question if you want to get a helpful answer.
Ocaml uses currying, which means that a two-argument function is the same thing that a function whose return value is a function.
To define a two-argument function, you can combine all the ways you know of creating one-argument functions:
let f x y = x + y
let f x = (fun y -> x + y)
let f x = function
| y -> x + y
let f = (fun x -> (fun y -> x + y))
let f = function
| x -> function
| y -> x + y
let f x = (let g y = x + y in g)
etc, etc.
All these definitions for f lead to the same result:
val f : int -> int -> int = <fun>
# f 3 4;;
- : int = 7
Note that the signature of f is:
val f : int -> int -> int = <fun>
If we added parentheses to better understand this signature, it would be this:
val f : int -> (int -> int) = <fun>
Meaning that f is a one-argument function whose return value is a one-argument function whose return value is an int.
Indeed, if we partially apply f:
# f 3;;
- : int -> int = <fun>
# let add_three = f 3;;
val add_three : int -> int = <fun>
# add_three 4;;
- : int = 7
The code you give at the end of your question is wrong. It's most likely intended to be this:
let reverse lst =
let rec aux acc l =
match l with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst;;
val reverse : 'a list -> 'a list = <fun>
# reverse [1;2;3;4;5];;
- : int list = [5; 4; 3; 2; 1]
I have a list of (string * int) list elements and I need to find the biggest int element and return the corresponding(string * int) element.
I have something like this atm, but problem is, I think my approach is more of "typical programming"
let it = [] in
for x = 0 to length LIST - 1 do
let str = ((List.nth LIST x).string) in
let num = ((List.nth LIST x).int) in
let it = it # [num, str] in
let (str, num) = List.hd(List.rev it) in
[str, num]
What I tried to do is to loop through the list and add the string and int value in another list, then sort them, reverse it and then take the head, which should be the max int, then I need to return the pair in (string * int)
Your code is not a well-formed OCaml code. It highlights, however, some number of issues with your understanding of OCaml.
First of all, by default, values in OCaml are immutable. For example,
let x = 0 in
for i = 0 to 10 do
let x = x + 1 in
print_int x;
done
You will get 11111111111 as the output. This is because, during the loop, you are just computing every time the x+1 expression, where x is always 0 and you will always get 1 as the result. This is because, let x = <expr> in <body> is not changing the existing variable x but is creating a new variable x (shadowing any previous definitions) and make it available in the scope of the <body> expression.
Concerning your problem in general, it should be solved as a recursive function greatest_element, which has the following definition,
for an empty list [] it is undefined;
for a list of one element [x] is it is x;
otherwise, for a list of x::xs it is max x (greatest_element xs),
where max x y is x if it is greater or equal to y.
Finally, it looks like you have missed the first steps in OCaml and before solving this task you have to move back and to learn the basics. In particular, you have to learn how to call functions, bind variables, and in general what are the lexical conventions and syntax of the language. If you need pointers, feel free to ask.
First of all, it doesn't seem that you did any kind of sorting in
the code that you provided.
Assuming that your list is of type
(string * int) list then a possible to find the element with the
maximum integer using recursion:
let max_in_list list =
let rec auxiliary max_str max_int = function
| []
-> (max_str, max_int)
| (crt_str, crt_int)::tail when crt_int > max_int
-> auxiliary crt_str crt_int tail
| _::tail
-> auxiliary max_str max_int tail
in
match list with
| []
-> None
| (fst_str, fst_int)::tail
-> Some (auxiliary fst_str fst_int tail)
let check = max_in_list [("some", 1); ("string", 3); ("values", 2)]
You could write a generic maxBy function. This allows you to get the max of any list -
let rec maxBy f = function
| [] -> None
| [ x ] -> Some x
| x :: xs ->
match (maxBy f xs) with
| Some y when (f y) > (f x) -> Some y
| _ -> Some x
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
let data = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]
(* val data : (string * int) list = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]*)
maxBy (fun (_, num) -> num) data
(* - : (string * int) option = Some ("c", 6) *)
maxBy (fun (str, _) -> str) data
(* - : (string * int) option = Some ("d", 1) *)
maxBy (fun x -> x) [3; 2; 6; 1]
(* - : int option = Some 6 *)
maxBy (fun x -> x) ["c"; "d"; "b"; "a"]
(* - : string option = Some "d" *)
maxBy (fun x -> x) []
(* - : 'a option = None *)
It can be fun to rewrite the same function in various ways. Here's another encoding -
let maxBy f list =
let rec loop r = function
| [] -> r
| x::xs when (f x) > (f r) -> loop x xs
| _::xs -> loop r xs
in
match list with
| [] -> None
| x::xs -> Some (loop x xs)
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
Suppose I have a (int list list) x = [[1;1;1]; [2;2;2]; [3;4;5]] and a function f. The result should be [f [1;1;1]; f [2;2;2]; f[3;4;5]]. The built in List.map works only for int list but not for int list list.The i-th entry in this new column is computed by the function f which is taking as input the i-th element from each column in the spreadsheet and forms a new element.
let newList x f = List.map f x (* this is the only map function that I know *)
You can use List.map f as a function, which works on one dimensional lists, and then map that function on the two-dimensional list as follows:
let x = [[1;1;1]; [2;2;2]; [3;4;5]];;
let f x = x + 1;;
List.map (List.map f) x;;
output:
- : int list list = [[2; 2; 2]; [3; 3; 3]; [4; 5; 6]]
my function will take as input two arguments, an int list list and a
function f. It will output a new int list. Input = m = [[x1;x2;x3] ;
[y1;y2;y3] ; [z1;z2;z3]] and function f Output = [f [x1;y1;z1] ; f
[x2;y2;z2] ; f [x3;y3;z3]]
It seems that you wanted to transpose (https://stackoverflow.com/a/3989823/4196578) your 2-D array and then map f. In that case, you can do:
let rec transpose list = match list with
| [] -> []
| [] :: xss -> transpose xss
| (x::xs) :: xss ->
(x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss);;
let myfunc m f = List.map f (transpose m);;
Very often when writing generic code in F# I come by a situation similar to this (I know this is quite inefficient, just for demonstration purposes):
let isPrime n =
let sq = n |> float |> sqrt |> int
{2..sq} |> Seq.forall (fun d -> n % d <> 0)
For many problems I can use statically resolved types and get even a performance boost due to inlining.
let inline isPrime (n:^a) =
let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
let sq = n |> float |> sqrt |> int
{two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
The code above won't compile because of the upper sequence limit being a float. Nongenerically, I could just cast back to int for example.
But the compiler won't let me use any of these:
let sq = n |> float |> sqrt :> ^a
let sq = n |> float |> sqrt :?> ^a
and these two lead to a InvalidCastException:
let sq = n |> float |> sqrt |> box |> :?> ^a
let sq = n |> float |> sqrt |> box |> unbox
Also, upcast and downcast are forbidden.
let sq = System.Convert.ChangeType(n |> float |> sqrt, n.GetType()) :?> ^a works, but seems very cumbersome to me.
Is there a way that I overlooked or do I really have to use the last version? Because the last one will also break for bigint, which I need quite often.
With the trick from FsControl, we can define generic function fromFloat:
open FsControl.Core
type FromFloat = FromFloat with
static member instance (FromFloat, _:int32 ) = fun (x:float) -> int x
static member instance (FromFloat, _:int64 ) = fun (x:float) -> int64 x
static member instance (FromFloat, _:bigint ) = fun (x:float) -> bigint x
let inline fromFloat (x:float):^a = Inline.instance FromFloat x
let inline isPrime (n:^a) =
let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
let sq = n |> float |> sqrt |> fromFloat
{two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
printfn "%A" <| isPrime 71
printfn "%A" <| isPrime 6L
printfn "%A" <| isPrime 23I
Inline.instance was defined here.
I have a function where I want to transform a list of floats into another one, where for each element I want to have x percent of element i spill over into element i + 1
example:
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
then p3_s should be:
[0.05; 0.15; 0.3; 0.3; 0.2]
To do this I took half of each element and added it to the next element.
0.1 became 0.05 because it gave 0.05 to the next, there is no previous element
0.2 became 0.15 because it gave 0.1 to the next and got 0.05 from the
first
etc
and finally 0.1 became 0.2 because it .01 from the
previous. There is no next element.
Now I came up with this which works but only for list of size 5:
// create list
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| 4 -> stay + fst ms.[i-1] + move // note hardcoded 4
| _ -> stay + fst ms.[i-1])
// get shifted list
shiftList p3 0.5
Now for the questions:
1) How do I make it match on any length list? Now I hardcoded the 4 in the match expression but I'd like to be able to accept any lenght list.
I tried this:
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// find length
let last = orgList.Length - 1
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| last -> stay + fst ms.[i-1] + move
| _ -> stay + fst ms.[i-1]) // now this one will never be matched
But this will not treat last as the number 4, instead it becomes a variable for i even though last is already declared above.
So how could I match on a variable, so that I can treat the last elmement differently? Finding the first one is easy because it's at 0.
2) How would you do this? I'm still pretty fresh to F# there are many things I don't know about yet. Guess the general case here is: how do I map a different function to the first and last element of a list, and a general one to the others?
Thanks in advance,
Gert-Jan
Here is a more functional solution
let func (input:float list) =
let rec middle_end input_ =
match input_ with
|h::t::[] -> ((h/2.0)+t)::[]
|h::t::tt ->((h+t)/2.0)::(middle_end (t::tt))
| _ -> [] //fix short lists
let fst = input.Head/2.0
fst::middle_end(input)
Also, this only requires a single pass through the list, rather than the 3 in Ramon's solution, as well as less temporary storage.
As an alternative to writing your own recursive function, you can also use built-in functions. The problem can be solved quite easily using Seq.windowed. You still need a special case for the last element though:
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
// Prefix zero before the list, pre-calculate the length
let p3' = (0.0 :: p3)
let l = p3.Length
// Perform the transformation
p3'
|> Seq.windowed 2
|> Seq.mapi (fun i ar ->
(if i = l - 1 then ar.[1] else ar.[1] / 2.0) + ar.[0] / 2.0)
|> List.ofSeq
You want to do:
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// find length
let last = orgList.Length - 1
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| last' when last' = last -> stay + fst ms.[i-1] + move
| _ -> stay + fst ms.[i-1]) // now this one will never be matched
Using List.scan:
let lst = [0.1; 0.2; 0.4; 0.2; 0.1]
let len = (lst.Length-1)
lst
|> List.mapi (fun i e -> (i,e))
|> List.scan (fun (c,_) (i,e) -> if i = len then (0.0,e+c) else ((e/2.0),(e/2.0)+c)) (0.0,0.0) |> List.tail
|> List.map snd
Just another idea,
let bleh p3 =
match Seq.fold (fun (give,acc) i -> i*0.5,((i*0.5 + give) :: acc)) (0.0,[]) p3 with
|(give,h::t) -> give+h :: t |> List.rev
|(_,[]) -> []