OCaml matrix manipulation - function

I'm looking to write an OCaml function with this structure:
rows : int list list -> char list -> int list = <fun>.
I'm having some trouble as I'm fairly new to the language.
The program should take each list and perform an operation like addition or multiplication with it's elements. For example: rows [[1;2;0];[4;5;6];[1;2;9]] [’+’;’-’;’*’];;-: int list = [3;-7;18]
Thank you in advance for any help.

Is this the basic problem? Note: I left important part for you to answer.
let nums =
[
[1;2;0];
[4;5;6];
[1;2;9];
]
let ops = ['+'; '-'; '*';]
let rec rows l o =
match (l, o) with
| ([],[]) -> []
| (hd::tl, op::tlo) ->
(
match hd with
| [] -> 0::(rows tl tlo)
| h::t -> (*The important part goes here*)
)
| _ -> failwith "Uneven list"
let ans = rows nums ops

Related

What is wrong with this code for creating lists in OCaml?

I am trying to create a program in OCaml [randlist len max], which would generate an int list of length len with integers smaller than max.
I am wondering what is wrong with the following code:
let randlist dolzina maksimum =
let rec aux dolz maks acc =
match (List.length acc) with
| dolz -> acc
| _ -> aux dolz maks ((Random.int maks) :: acc)
in
aux dolzina maksimum []
This always returns an empty list and I do not understand why.
Another thing that confuses me is what goes wrong with the following code:
let randlist dolzina maksimum =
Random.self_init ()
let rec aux dolz maks acc =
match (List.length acc) with
| dolz -> acc
| _ -> aux dolz maks ((Random.int maks) :: acc)
in
aux dolzina maksimum []
As soon as I add the Random.self init () the whole code crashes. What exactly does Random.self_init do, when and how do I use it?
You are using match as if it is going to compare two integer values, but that's not how it works. This match:
Match List.length acc with
| dolz -> ...
Will always match the first case. The name dolz is a new variable that is bound to the length of the list. The outer definition of dolz is not relevant here, a pattern introduces new names.
If you want to compare two integer values, you should use if:
if List.length acc = dolz then
...
else
...
Pattern matching deconstructs values that match a pattern into smaller parts, it doesn't test equality. In other words, your first case
match List.length acc with
| dolz -> acc
reads: take the value returned by List.length acc, name it dolz in the right hand side of the arrow ->, and run the code after ->. Notice that this means that dolz matches any values.
This is why the compiler warns you that the second case
| _ -> aux dolz maks ((Random.int maks) :: acc)
is never used.
For your second question, the code cannot crash, since your code is not well-typed and thus cannot compile. Random.self_init initialize the seed of the PRNG. You should call it once in your program, and not at every calls of randlist.
What you're trying to accomplish can be implemented without having to calculate the length of the accumulated list. You just need to count the length parameter down by one on each iteration and return acc when it is less than or equal to 0.
let randlist count max =
let rec aux c m acc =
if c <= 0 then acc
else aux (c-1) m (Random.init max :: acc)
in
aux count max []
Of course, all of this is just a convoluted way to write:
let randlist count max =
List.init count (fun _ -> Random.int max)
Here the List.init function takes care of the iteration for us. Implementing an equivalent function may shed some light on how it works.
let list_init n f =
let rec list_init' n f acc =
if n <= 0 then acc
else list_init' (n-1) f (f (n-1) :: acc)
in
list_init' n f []

In F#, is it possible to check if two values have the same constructor?

Assuming I have a big discriminated union type:
type Thing =
| One of int
| Two of string
| Three of bool option
...
And I have this function:
let comp a b = match a, b with
| One _, One _ -> true
| Two _, Two _ -> true
...
| _, _ -> false
Is there a way to write the function in a neater, shorter way that doesn't require me to list every single constructor?
Basically, this is not possible. Even if you could get the constructors for your values, they are not comparable because they are functions. There's a bit of boilerplate involved but you could define tag values and a function to map to the tags:
let thingCase thing =
match thing with
| One _ -> 1
| Two _ -> 2
| Three _ -> 3
let comp a b = thingCase a = thingCase b
This is flexible enough to work on sequences too:
let compSeq things =
things
|> Seq.map thingCase
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> a = b)
Note: you could also do this with reflection but it's generally best to avoid.
I'm not quite sure how good it is performance-wise, but it is possible to do this using FSharp.Reflection.
open FSharp.Reflection
type Thing =
| One of int
| Two of string
| Three of bool option
let tagOfThing = FSharpValue.PreComputeUnionTagReader(typeof<Thing>)
// val tagOfThing : obj -> int
let isSameThingCase (a: Thing) (b: Thing) =
tagOfThing a = tagOfThing b
Use:
> isSameThingCase (One 1) (One 2);;
val it : bool = true
> isSameThingCase (Two "test") (Three None);;
val it : bool = false

Recursive call in if expression - ocaml

module Dfs = struct
let rec dfslsts g paths final =
let l = PrimePath.removeDuplicates (PrimePath.extendPaths g paths)
in
let f elem =
if (List.mem "%d" (List.flatten final) = false) then (dfslsts g ["%d"] (List.flatten l)::final)
else final
in
List.iter f (Graph.nodes g)
end
Error: This expression has type string but an expression was expected of type int list
This error occurred when I called dfslsts function, which is recursive, inside the if condition.
The function dfslsts returns a list of lists.
If I try to replace the complex expression in if statement to
if (List.mem "%d" (List.flatten final) = false) then "%d"
else "%d"
then I get
Error: This expression has type 'a -> string
but an expression was expected of type 'a -> unit
Type string is not compatible with type unit
at List.iter line.
How do I solve this problem and are we allowed to call a recursive function inside the if expression.
This is the definition of my graph type:
module Graph = struct
exception NodeNotFound of int
type graph = {
nodes : int list;
edges : (int * int) list;
}
let makeGraph () =
{
nodes = [];
edges = [];
}
let rec isNodeOf g n = List.mem n g.nodes
let nodes g = g.nodes
let edges g = g.edges
let addNode g n =
let nodes = n::g.nodes and edges = g.edges in
{
nodes;
edges;
}
let addEdge g (n1, n2) =
if ((isNodeOf g n1) = false) then
raise (NodeNotFound n1)
else if ((isNodeOf g n2) = false) then
raise (NodeNotFound n2)
else
let nodes = g.nodes
and edges = (n1, n2) :: g.edges in
{
nodes;
edges;
}
let nextNodes g n =
let rec findSuccessors edges n =
match edges with
[] -> []
| (n1, n2) :: t ->
if n1 = n then n2::findSuccessors t n
else findSuccessors t n
in
findSuccessors g.edges n
let rec lastNode path =
match path with
[] -> raise (NodeNotFound 0)
| n :: [] -> n
| _ :: t -> lastNode t
end
module Paths = struct
let extendPath g path =
let n = (Graph.lastNode path) in
let nextNodes = Graph.nextNodes g n in
let rec loop path nodes =
match nodes with
[] -> []
| h :: t -> (List.append path [h]) :: (loop path t)
in
loop path nextNodes
let rec extendPaths g paths =
match paths with
[] -> []
| h :: t -> List.append (extendPath g h) (extendPaths g t)
(* Given a list lst, return a new list with all duplicate entries removed *)
let rec removeDuplicates lst =
match lst with
[]
| _ :: [] -> lst
| h :: t ->
let trimmed = removeDuplicates t in
if List.mem h trimmed then trimmed
else h :: trimmed
end
Any expression can be a recursive function call. There are no limitations like that. Your problem is that some types don't match.
I don't see any ints in this code, so I'm wondering where the compiler sees the requirement for an int list. It would help to see the type definition for your graphs.
As a side comment, you almost certainly have a precedence problem with this code:
dfslsts g ["%d"] (List.flatten l)::final
The function call to dfslsts has higher precedence that the list cons operator ::, so this is parsed as:
(dfslsts g ["%d"] (List.flatten l)) :: final
You probably need to parenthesize like this:
dfslsts g ["%d"] ((List.flatten l) :: final)

Is it possible to write a recursive grouping function like this in f#

Lets say you had a requirement to group a sequence into a sequence of tuples. Each tuple is a key*seq. So in a sense, the result is a sequence of sequences.
All pretty standard so far.
What if you wanted to further group each sub sequence by some other key? It would be easy enough to map another groupby function onto each element of your sequence of sequences. You would then have a sequence of sequences of sequences.
Starting to get slightly hairy.
What if you wanted to group it even further?
Would it be possible to write a function that can take in a key generating function and an arbitrary sequence, and recursively unwraps the layers and then adds another layer of grouping using the keyFunction?
I suspect the answer is no, because the recursive function would not have a well defined type.
My attempt at this, to further illustrate the idea:
let rec recursiveGrouper keyFunction aSeq =
let first = Seq.head aSeq
match first with
| ((a:'a), _) -> Seq.map (fun (b,(c:seq<'c>)) -> (b, recursiveGrouper keyFunction c)) aSeq
| _ -> Seq.groupBy keyFunction aSeq
EDIT:
Lets add an example of how this might work, it it were possible
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr =
fr.Fruit
let key2 fr =
fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
Lets say we have a whole bunch of fruit records in a sequence. We want to group them by type of fruit.
One way would be to say
let group1 = fruitRecs |> Seq.groupBy key1
Using our recursive function, this would be
let group1 = recursiveGrouper key1 fruitRecs
Next, lets say we want to group each of the items in the groups of group1 by source farm.
We could say
let group2 =
group1
|> Seq.map (fun (f, s) -> (f, Seq.groupBy key2 s))
Using our recursive function it would be
let group2 = recursiveGrouper key2 group1
And we could go further and group by Grade by saying
let group3 = recursiveGrouper key3 group2
Actually there are some ways to make that recursive function work, using static constraints. Here's a small example:
// If using F# lower than 4.0, use this definition of groupBy
module List =
let groupBy a b = Seq.groupBy a (List.toSeq b) |> Seq.map (fun (a, b) -> a, Seq.toList b) |> Seq.toList
type A = class end // Dummy type
type B = class end // Dummy type
type C =
inherit B
static member ($) (_:C, _:A ) = fun keyFunction -> () // Dummy overload
static member ($) (_:C, _:B ) = fun keyFunction -> () // Dummy overload
static member ($) (_:B, aSeq) = fun keyFunction -> List.groupBy keyFunction aSeq // Ground case overload
static member inline ($) (_:C, aSeq) = fun keyFunction -> List.map (fun (b, c) -> b, (Unchecked.defaultof<C> $ c) keyFunction) aSeq
let inline recursiveGrouper keyFunction aSeq = (Unchecked.defaultof<C> $ aSeq) keyFunction
// Test code
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr = fr.Fruit
let key2 fr = fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
let fruitRecs = [
{Fruit = "apple" ; Number = 8; SourceFarm = "F"; Grade = 5.5}
{Fruit = "apple" ; Number = 5; SourceFarm = "F"; Grade = 4.5}
{Fruit = "orange"; Number = 8; SourceFarm = "F"; Grade = 5.5}
]
let group1 = recursiveGrouper key1 fruitRecs
let group2 = recursiveGrouper key2 group1
let group3 = recursiveGrouper key3 group2
I don't think you could write it as a recursive function with the sort of constraints you put on yourself - that is:
A tuple 'key * seq<'value> representing the grouping,
A heterogeneous key function (or a collection thereof) - this is what I understand by "group each sub sequence by some other key".
You could make some leeway if you would represent the grouping as an actual tree type (rather than an ad-hoc tree built from tuples) - that way you'd have a well-defined recursive result type to go with your recursive function.
If at that point you would be able to also compromise on the key function to make it homogeneous (worst case - producing a hashcode), you should be able to express what you want within the type system.
You certainly could have a non-recursive grouping function that takes a grouped sequence and puts another level of grouping on top of it - like the one below:
module Seq =
let andGroupBy (projection: 't -> 'newKey) (source: seq<'oldKey * seq<'t>>) =
seq {
for key, sub in source do
let grouped = Seq.groupBy projection sub
for nkey, sub in grouped do
yield (key, nkey), sub
}
Using your FruitRecord example:
values
|> Seq.groupBy key1
|> Seq.andGroupBy key2
|> Seq.andGroupBy key3

OCaml error : "the variant type has no constructor ::"

I'm studying OCaml right now, and after I do this,
type aexp =
| Const of int
| Var of string
| Power of string * int
| Times of aexp list
| Sum of aexp list
let rec diff : aexp * string -> aexp
=fun (aexp,x) -> match aexp with
|Const a -> Const 0
|Var "x" -> Const 1
|Power ("x", a) -> (match a with
|2 -> Times[Const 2; Var "x"]
|1 -> Const 1
|0 -> Const 0
|_ -> Times[Const a; Power ("x", a-1)])
|Times [l] -> (match l with
|h::t -> (match t with
|Var "x" -> h
|Power ("x",a) -> Times [Times [h;Const a];diff(Power ("x",a),x)]))
I get an error:
File "", line 11, characters 3-5:
Error: The variant type aexp has no constructor ::
I learned that :: is concatenation of single element to a list or another element of a list.
It worked with my other codes that used list.
Why isn't it working here?
Your pattern Times [l] matches a node Times with exactly one element named l. You wanted to write Times l, that matches a node Times with a list of any number of elements, bound to l in the body of the clause.
Note that in OCaml you can use nested pattern-matching, such as:
| Times (Var "x" :: _) -> h
| Times (Power ("x",a) :: _ ) -> ...
| ...