The task is to get scalar value from 2 lists recursively. I wrote the code that I think should work, but I am having some type related problem
let rec scalar2 (a, b) = function
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
The error is that scalar2 (t1,t2) reqested to be int, but it is int list * int list -> int
How this problem could be solved?
When defining a function using the function keyword, you don't need to name your parameters (a and b here). Note that your function body doesn't refer to a or b at all. You want scalar2 to be a function, and the function expression on the right hand side results in a function, so just assign this function to scalar2 directly.
let rec scalar2 = function
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
Your mistake is likely caused by a confusion with the usual way of defining a function, which doesn't use the function keyword:
let rec scalar2 (a,b) =
match (a,b) with
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
This way you need a match expression which does use the parameters a and b.
Note that both of these definitions are incomplete, since you haven't said what should happen when only one of the lists is non-empty.
To explain the type error in the original code, consider how F# evaluates let sc : int = scalar2 (t1,t2). Your original definition says that scalar2 (a,b) = function ..., and the left-hand side of this equality has the same form as the expression scalar2 (t1,t2).
So the scalar2 (t1,t2) gets replaced with the function ... expression, after substituting t1 for a and t2 for b. This leaves let sc : int = function ... which of course doesn't type-check.
I have a dictionary of operations:
type INumerics<'T> =
abstract Zer : 'T
abstract Add : 'T * 'T -> 'T
abstract Sub : 'T * 'T -> 'T
abstract Mul : 'T * 'T -> 'T
abstract Div : 'T * 'T -> 'T
abstract Neq : 'T * 'T -> bool
With helper functions:
let inline add (x : 'T) (y : 'T) : 'T = (+) x y
let inline sub (x : 'T) (y : 'T) : 'T = (-) x y
let inline mul (x : 'T) (y : 'T) : 'T = (*) x y
let inline div (x : 'T) (y : 'T) : 'T = (/) x y
let inline neq (x : 'T) (y : 'T) : bool = (<>) x y
Then we have a simple calculator using a MailboxProcessor agent:
type Agent<'T> = MailboxProcessor<'T>
type CalculatorMsg<'T> =
| Add of 'T * 'T * AsyncReplyChannel<'T>
| Sub of 'T * 'T * AsyncReplyChannel<'T>
| Mul of 'T * 'T * AsyncReplyChannel<'T>
| Div of 'T * 'T * AsyncReplyChannel<'T>
type CalculatorAgent< ^T when ^T : (static member get_Zero : unit -> ^T)
and ^T : (static member Zero : ^T)
and ^T : (static member (+) : ^T * ^T -> ^T)
and ^T : (static member (-) : ^T * ^T -> ^T)
and ^T : (static member (*) : ^T * ^T -> ^T)
and ^T : (static member (/) : ^T * ^T -> ^T)
and ^T : equality >() =
let agent =
let ops =
{ new INumerics<'T> with
member ops.Zer = LanguagePrimitives.GenericZero<'T>
member ops.Add(x, y) = (x, y) ||> add
member ops.Sub(x, y) = (x, y) ||> sub
member ops.Mul(x, y) = (x, y) ||> mul
member ops.Div(x, y) = (x, y) ||> div
member ops.Neq(x, y) = (x, y) ||> neq }
Agent<CalculatorMsg<'T>>.Start(fun inbox ->
let rec loop () =
async {
let! msg = inbox.TryReceive()
if msg.IsSome then
match msg.Value with
| Add (x, y, rep) ->
printfn "Adding %A and %A ..." x y
let res = ops.Add(x, y)
res |> rep.Reply
return! loop()
| Sub (x, y, rep) ->
printfn "Subtracting %A from %A ..." y x
let res = ops.Sub(x, y)
res |> rep.Reply
return! loop()
| Mul (x, y, rep) ->
printfn "Multiplying %A by %A ... " y x
let res = ops.Mul(x, y)
res |> rep.Reply
return! loop()
| Div (x, y, rep) ->
printfn "Dividing %A by %A ..." x y
if ops.Neq(y, ops.Zer) then
let res = ops.Div(x, y)
res |> rep.Reply
else
printfn "#DIV/0"
return! loop()
else
return! loop()
}
loop()
)
// timeout = infinit => t = -1
let t = 1000
member inline this.Add(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Add (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Subtract(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Sub (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Multiply(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Mul (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Divide(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Div (x, y, rep)), t)
|> Async.RunSynchronously
As a use example, we have:
let calculatorAgentI = new CalculatorAgent<int>()
(2, 1) |> calculatorAgentI.Add
(2, 1) |> calculatorAgentI.Subtract
(2, 1) |> calculatorAgentI.Multiply
(2, 1) |> calculatorAgentI.Divide
(2, 0) |> calculatorAgentI.Divide
The issue is that Add and Multiply and the Last Divide work ok:
>
Adding 2 and 1 ...
val it : int option = Some 3
>
Multiplying 1 by 2 ...
val it : int option = Some 2
>
Dividing 2 by 0 ...
#DIV/0
val it : int option = None
As soon as we use Subtract and first Divide which would return int option = None, I get into trouble and the following is the only output I would get from any of the operations:
>
val it : int option = None
As long and hard as I think about it, I cannot figure out if there is a problem in the "subtract"/"divide" part or the "receive"/"reply" operations.
Running this code with the Debugger attached, you'll see that you get a System.NotSupportedException when trying to run the sub function from inside the agent:
System.NotSupportedException occurred
HResult=0x80131515
Message=Specified method is not supported.
Source=FSI-ASSEMBLY
StackTrace:
at FSI_0002.ops#60.FSI_0002-INumerics`1-Sub(T X1, T X2)
The reason you get val it : int option = None is because you have specified a 1-second timeout, and you are hitting that after the exception is thrown.
Calling the sub function directly works fine, but calling it through the CalculatorAgent class does not. This is because the type parameters are defined on the class in this case, and there are limitations on the use of structural type constraints on classes in F#. I would suggest reading up on Statically Resolved Type Parameters and their limitations.
The behaviour seems to be an irregularity or a bug. I was also expecting that this would behave the same for all operations.
In any case, you can workaround this by capturing ops in a static inline member (rather than using statically resolved type parameters on a type). The following works fine for me:
type CalculatorAgent<'T>(ops:INumerics<'T>) =
let agent =
Agent<CalculatorMsg<'T>>.Start(fun inbox ->
let rec loop () = async {
let! msg = inbox.TryReceive()
match msg with
| Some(Add (x, y, rep)) ->
printfn "Adding %A and %A ..." x y
let res = ops.Add(x, y)
res |> rep.Reply
return! loop()
| Some(Sub (x, y, rep)) ->
printfn "Subtracting %A from %A ..." y x
let res = ops.Sub(x, y)
res |> rep.Reply
return! loop()
| Some(Mul (x, y, rep)) ->
printfn "Multiplying %A by %A ... " y x
let res = ops.Mul(x, y)
res |> rep.Reply
return! loop()
| Some(Div (x, y, rep)) ->
printfn "Dividing %A by %A ..." x y
if ops.Neq(y, ops.Zer) then
let res = ops.Div(x, y)
res |> rep.Reply
else
printfn "#DIV/0"
return! loop()
| _ ->
return! loop() }
loop() )
// timeout = infinit => t = -1
let t = 1000
member this.Add(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Add (x, y, rep)), t)
|> Async.RunSynchronously
member this.Subtract(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Sub (x, y, rep)), t)
|> Async.RunSynchronously
member this.Multiply(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Mul (x, y, rep)), t)
|> Async.RunSynchronously
member this.Divide(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Div (x, y, rep)), t)
|> Async.RunSynchronously
type CalculatorAgent =
static member inline Create() =
let ops =
{ new INumerics<_> with
member ops.Zer = LanguagePrimitives.GenericZero<_>
member ops.Add(x, y) = x + y
member ops.Sub(x, y) = x - y
member ops.Mul(x, y) = x * y
member ops.Div(x, y) = x / y
member ops.Neq(x, y) = x <> y }
CalculatorAgent<_>(ops)
let calculatorAgentI = CalculatorAgent.Create<int>()
(2, 1) |> calculatorAgentI.Add
(2, 1) |> calculatorAgentI.Subtract
(2, 1) |> calculatorAgentI.Multiply
(2, 1) |> calculatorAgentI.Divide
(2, 0) |> calculatorAgentI.Divide
That said, I think the cases where you really need generic numerical code are pretty rare - so I suspect it might be better to avoid introducing all this complexity altogether and just write the code for a specific numerical type.
Is there any way to use the decide equality tactic with mutually recursive types in Coq?
For example, if I've got something like this:
Inductive LTree : Set :=
| LNil
| LNode (x: LTree) (y: RTree)
with RTree : Set :=
| RNil
| RNode (x: Tree) (y: RTree).
Lemma eq_LTree : forall (x y : LTree), {x = y} + {x <> y}.
Proof.
decide equality; auto.
This leaves me with the goal:
y0: RTree
y1: RTree
{y0 = y1} + {y0 <> y1}
But I can't solve that until I've derived equality for RTree, which will have the same problem.
You can use decide equality in this case if you prove the two lemmas for LTrees and RTrees simultaneously:
Lemma eq_LTree : forall (x y : LTree), {x = y} + {x <> y}
with eq_RTree : forall (x y : RTree), {x = y} + {x <> y}.
Proof.
decide equality.
decide equality.
Qed.
I'm using VST v1.7.
Has anyone ever proved that an int is equal as an array of characters? Something along those lines:
Definition int2uchars (i : int) : list Z :=
[
Int.unsigned (Int.and (Int.shru i (Int.repr 24)) (Int.repr 255));
Int.unsigned (Int.and (Int.shru i (Int.repr 16)) (Int.repr 255));
Int.unsigned (Int.and (Int.shru i (Int.repr 8)) (Int.repr 255));
Int.unsigned (Int.and (Int.shru i (Int.repr 0)) (Int.repr 255))
].
Lemma int2chararray :
forall (i : int) (v : val),
field_at Tsh tuint [] (Vint i) v
= data_block Tsh (int2uchars i) v.
Is there another solution than breaking the field_at abstraction to prove that?
I have written myPercolation.ml.
open MyUnionFind
module type MyPercolationSig = sig
type percolation
val create_percolation : int -> percolation
val open_site : percolation -> int -> int -> unit
val is_open : percolation -> int -> int -> bool
val is_full : percolation -> int -> int -> bool
val can_percolates : percolation -> bool
end
module MyPercolation : MyPercolationSig = struct
exception IndexOutOfBounds;;
type percolation =
{n : int;
sites: bool array;
union : MyUnionFind.union_find};;
let create_percolation n =
{n = n; sites = Array.make (n*n) false; union = MyUnionFind.create_union (n*n)};;
let open_site p i j =
let {n;_;union} = p
in
if not (is_open p i j) then
begin
sites.(index_of n i j) <- true;
if i - 1 >= 1 && i - 1 <= n && is_open n (i-1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i-1) j)
else if i + 1 >= 1 && i + 1 <= n && is_open n (i+1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i+1) j)
else if j - 1 >= 1 && j - 1 <= n && is_open n i (j-1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j-1))
else if j + 1 >= 1 && j + 1 <= n && is_open n i (j+1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j+1))
end;;
let index_of n i j = n * (i - 1) + j;;
let is_open {n;sites;_} i j =
if i < 1 || i > n || j < 1 || j > n then
raise IndexOutOfBounds
else
sites.(index_of n i j);;
let is_full {n;_;union} i j =
let rec is_connected_top j' =
if j = 0 then false
else
if MyUnionFind.is_connected union (index_of n i j) (index_of n 0 j') then true
else is_connected_top (j'-1)
in is_connected_top n;;
let can_percolates p =
let {n;_;_} = p
in
let rec is_full_bottom j =
if j = 0 then false
else
if is_full p n j then true
else is_full_bottom (j-1)
end
Please ignore the package MyUnionFind package. It is just a homemade implementation for union-find algorithm.
when I try to compile the myPercolation.ml, I got such an error:
$ ocamlc -c myPercolation.ml
File "myPercolation.ml", line 25, characters 11-12:
Error: Syntax error: '}' expected
File "myPercolation.ml", line 25, characters 8-9:
Error: This '{' might be unmatched
I think the error is talking about let {n;_;union} = p in function of let open_site p i j.
I have read through that line and all code many times, but I still don't see any mismatched {} in that line.
can anyone help please?
Another possible error: {n;_;_} should be {n;_} Only 1 underscore is necessary. Think of it like the _ wildcard in a match statement.
The expression let {n; _; union} = p is not well formed OCaml. I think what you want is let {n; union} = p. The way to handle fields you don't care about in a record pattern is not to mention them.
Update:
As rgrinberg points out, a much better way to describe the problem is that the _ has to appear as the last field. That's why the compiler is expecting to see } afterward. It might be good style to include the _ as an indicator that you're purposely matching only a subset of the fields of the record. You can, in fact, turn on a compiler option that checks for this.
Update 2:
The warning for incomplete record patterns is warning number 9, and also is associated with the letter R. Here's how to use R:
$ ocaml -w +R
OCaml version 4.00.0
# type r = { a: int; b: char };;
type r = { a : int; b : char; }
# let {a} = {a=3; b='x'} in a;;
Warning 9: the following labels are not bound in this record pattern:
b
Either bind these labels explicitly or add '; _' to the pattern.
- : int = 3
The command-line syntax is the same for the compiler.