I've created a mutable data structure in OCaml, however when I go to access it, it gives a weird error,
Here is my code
type vector = {a:float;b:float};;
type vec_store = {mutable seq:vector array;mutable size:int};;
let max_seq_length = ref 200;;
exception Out_of_bounds;;
exception Vec_store_full;;
let vec_mag {a=c;b=d} = sqrt( c**2.0 +. d**2.0);;
let make_vec_store() =
let vecarr = ref ((Array.create (!max_seq_length)) {a=0.0;b=0.0}) in
{seq= !vecarr;size=0};;
When I do this in ocaml top-level
let x = make _ vec _store;;
and then try to do x.size I get this error
Error: This expression has type unit -> vec_store
but an expression was expected of type vec_store
Whats seems to be the problem? I cant see why this would not work.
Thanks,
Faisal
make_vec_store is a function. When you say let x = make_vec_store, you are setting x to be that function, just like if you'd written let x = 1, that would make x the number 1. What you want is the result of calling that function. According to make_vec_store's definition, it takes () (also known as "unit") as an argument, so you would write let x = make_vec_store ().
try x = make_ vec_store()
As a follow up to the excellent answere provided. You can tell that your example line:
# let x = make_vec_store;;
val x : unit -> vec_store = <fun>
returns a function as the repl will tell you this. You can see from the output that x is of type <fun> that takes no parameters unit and returns a type vec_store.
Contrast this to the declaration
# let x = 1;;
val x : int = 1
which tells you that x is of type int and value 1.
Related
I created a function p that checks if the square of a given value is lower than 30.
Then this function is called in an other function (as argument) to return the first value inside a list with its square less then 30 ( if p is true, basically I have to check if the function p is true or false ).
This is the code :
let p numb =
let return = (numb * numb) < 30 in return
let find p listT =
let rec support p listT =
match listT with
| []-> raise (Failure "No element in list for p")
| hd :: tl -> if p hd then hd
else support p tl in
let ret = support (p listT) in ret
let () =
let a = [5;6;7] in
let b = find p a in print_int b
But it said on the last line :
Error: This expression (p) has type int -> bool
but an expression was expected of type int -> 'a -> bool
Type bool is not compatible with type 'a -> bool
However, I don't think I'm using higher order functions in the right way, I think it should be more automatic I guess, or not?
First, note that
let return = x in return
can replaced by
x
Second, your original error is on line 10
support (p listT)
This line makes the typechecker deduce that the p argument of find is a function that takes one argument (here listT) and return another function of type int -> bool.
Here's another way to look at your problem, which is as #octachron says.
If you assume that p is a function of type int -> bool, then this recursive call:
support (p listT)
is passing a boolean as the first parameter of support. That doesn't make a lot of sense since the first parameter of support is supposed to be a function.
Another problem with this same expression is that it requires that listT be a value of type int (since this is what p expects as a parameter). But listT is a list of ints, not an int.
A third problem with this expression is that it only passes one parameter to support. But support is expecting two parameters.
Luckily the fix for all these problems is exremely simple.
I'm constructing a simple type provider, but I seem to be running into problems when referencing types I created. For instance, given
namespace Adder
type Summation = Summation of int
module QuickAdd =
let add x y = x + y |> Summation
I want to make the following test case pass:
module Adder.Tests
open Adder
open NUnit.Framework
type Simple = QuickAddProvider<1, 2>
[<Test>]
let ``Simple sample is 3`` () =
let foo = Simple()
Assert.AreEqual(foo.Sample, Summation 3)
With the following type provider:
namespace Adder
open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
[<TypeProvider>]
type public QuickAddProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces ()
let ns = "Adder"
let asm = Assembly.GetExecutingAssembly()
let paraProvTy = ProvidedTypeDefinition(asm, ns, "QuickAddProvider", Some typeof<obj>)
let buildTypes (typeName:string) (args:obj[]) =
let num1 = args.[0] :?> int
let num2 = args.[1] :?> int
let tpType = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>)
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args -> <## result ##>))
tpType.AddMember(orig)
tpType.AddMember(ProvidedConstructor([], InvokeCode = (fun args -> <## () ##>)))
tpType
let parameters =
[ProvidedStaticParameter("Num1", typeof<int>)
ProvidedStaticParameter("Num2", typeof<int>)]
do paraProvTy.DefineStaticParameters(parameters, buildTypes)
do this.AddNamespace(ns, [paraProvTy])
[<TypeProviderAssembly>]
do()
I run into unexpected errors in the test file:
The type provider 'Adder.QuickAddProvider' reported an error in the context of provided type 'Adder.QuickAddProvider,Num1="1",Num2="2"', member 'get_Sample'. The error: Unsupported constant type 'Adder.Summation'
With the following errors in the generated file:
The type "Summation" is not defined
The namespace or module "Adder" is not defined
The test case compiles and passes when replacing the Summation type with int, so I know my type provider isn't terribly wrong. Do I need to somehow "import" the Summation type somewhere?
This error usually means that you are creating a quotation that contains a value of custom type. The quotations in type providers can only contain values of primitive types - the compiler knows how to serialize these - but it cannot handle custom types.
In the snippet, this happens here:
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args ->
<## result ##>))
Here, the GetterCode returns a quotation containing value of type Summation which is not supported. To make this work, you can do various things - generally, you'll need to come up with some other quoted expression that produces the value you want.
One option is to do the calculation inside the quotation rather than outside:
<## QuickAdd.add num1 num2 ##>
The other option would be to re-create the Summation value in the quotation:
let (Summation n) = result
<## Summation n ##>
This works, because it only needs to serialize a primitive int value and then generate a call to the Summation case constructor.
I defined a higher-order function like this:
val func : int -> string -> unit
I would like to use this function in two ways:
other_func (func 5)
some_other_func (fun x -> func x "abc")
i.e., by making functions with one of the arguments already defined. However, the second usage is less concise and readable than the first one. Is there a more readable way to pass the second argument to make another function?
In Haskell, there's a function flip for this. You can define it yourself:
let flip f x y = f y x
Then you can say:
other_func (func 5)
third_func (flip func "abc")
Flip is defined in Jane Street Core as Fn.flip. It's defined in OCaml Batteries Included as BatPervasives.flip. (In other words, everybody agrees this is a useful function.)
The question posed in the headline "change order of parameters" is already answered. But I am reading your description as "how do I write a new function with the second parameter fixed". So I will answer this simple question with an ocaml toplevel protocol:
# let func i s = if i < 1 then print_endline "Counter error."
else for ix = 1 to i do print_endline s done;;
val func : int -> string -> unit = <fun>
# func 3 "hi";;
hi
hi
hi
- : unit = ()
# let f1 n = func n "curried second param";;
val f1 : int -> unit = <fun>
# f1 4;;
curried second param
curried second param
curried second param
curried second param
- : unit = ()
#
I have a little problems here that I don't 100% understand:
let x = 1 in let x = x+2 in let x = x+3 in x
I know the result of this expression is 6, but just want to make sure the order of calculating this expression; which part is calculated first?
You asked about the order of the evaluation in the expression let x=1 in let x=x+2 in .... The order is "left-to-right"! When you have a chain of let a=b in let c=d in ..., the order of evaluation is always left-to-right.
However, in your example there is a confusing part: you used the same variable name, x, in every let construct. This is confusing because you then see things like let x=x+1, and this looks like you are "redefining" x or "changing the value of x". But no "changing" of "x" actually happens here in OCAML! What happens here, as already pointed out above, is that a new variable is introduced every time, so your example is entirely equivalent to
let x = 1 in let y = x+2 in let z = y+3 in z;;
Note that here the order of evaluation is also left-to-right. (It is always left-to-right in every chain of let constructs.) In your original question, you chose to call all these new variables "x" rather than x, y, and z. This is confusing to most people. It is better to avoid this kind of coding style.
But how do we check that we renamed the variables correctly? Why "let x=1 in let y=x+2" and not "let x=1 in let x=y+2"? This x=x+2 business is quite confusing! Well, there is another way of understanding the evaluation of let x=aaa in bbb. The construct
let x=aaa in bbb
can be always replaced by the following closure applied to aaa,
(fun x -> bbb) aaa
Once you rewrite it in this way, you can easily see two things: First, OCAML will not evaluate "bbb" inside the closure until "aaa" is evaluated. (For this reason, the evaluation of let x=aaa in bbb proceeds by first evaluating aaa and then bbb, that is, "left-to-right".) Second, the variable "x" is confined to the body of the closure and so "x" cannot be visible inside the expression "aaa". For this reason, if "aaa" contains a variable called "x", it must be already defined with some value before, and it has nothing to do with the "x" inside the closure. For reasons of clarity, it would be better to call this variable by a different name.
In your example:
let x=1 in let x=x+2 in let x=x+3 in x
is rewritten as
(fun x -> let x=x+2 in let x=x+3 in x) 1
Then the inner let constructs are also rewritten:
(fun x -> (fun x -> let x=x+3 in x) x+2 ) 1
(fun x -> (fun x -> (fun x-> x) x+3) x+2 ) 1
Now let us rename the arguments of functions inside each function, which we can always do without changing the meaning of the code:
(fun x -> (fun y -> (fun z -> z) y+3) x+2 ) 1
This is the same as
let x=1 in let y=x+2 in let z=y+3 in z
In this way, you can verify that you have renamed the variables correctly.
Imagine parens:
let x = 1 in (let x = (x+2) in (let x = (x+3) in x))
Then substitute (x=1) where x it's not covered by another declaration of x and eliminate outermost let:
let x = (1+2) in (let x = (x+3) in x)
Evaluate:
let x = 3 in (let x = (x+3) in x)
Substitute:
let x = (3+3) in x
Evaluate:
let x = 6 in x
Substitute:
6
(This is a little long for a comment, so here's a smallish extra answer.)
As Chuck points out, there is no closure involved in this expression. The only complexity at all is due to the scoping rules. OCaml scoping rules are the usual ones, i.e., names refer to the nearest (innermost) definition. In the expression:
let v = e1 in e2
The variable v isn't visible (i.e., cannot be named) in e1. If (by chance) a variable of that name appears in e1, it must refer to some outer definition of (a different) v. But the new v can (of course) be named in e2. So your expression is equivalent to the following:
let x = 1 in let y = x+2 in let z = y+3 in z
It seems to me this is clearer, but it has exactly the same meaning.
I have a function that takes in a temp, which is a pair.
type temp = (pd * string);;
I want to extract that string in temp. But I can't write a function that can just match on temp since its a type.
I wrote a function:
let print_temp(t:temp) (out: out_channel) : unit =
fun z -> match z with
(_,a) -> output_string out a "
;;
But that gives me an error saying its not a function. I basically want to extract that string and print it. Any input on this would be appreciated.
Your solution is almost correct -- you don't need the "fun z ->" part, and it looks like you might have an extraneous ". Instead, you need to pattern match against t, like this:
let print_temp (t:temp) (out:out_channel) : unit =
match t with
(_,a) -> output_string out a
You can also do this more succinctly by pattern matching in the function definition:
let print_temp ((_,a):temp) (out:out_channel) : unit = output_string out a
In your code, the type error you get is telling you that you declared print_temp to return unit, but actually returned a function (fun z -> ...). Note that since the t:temp is what you want to "take apart", it makes sense that you would pattern match on it.
Instead of
match t with (_, a) -> output_string out a
you can also use the functions fst (and snd)
let a = fst t in output_string out a
or even more concise
output_string out (fst t)