I have a type Foo with a constructor that takes an Int. How do I define an implicit Arbitrary for Foo to be used with scalacheck?
implicit def arbFoo: Arbitrary[Foo] = ???
I came up with the following solution, but it's a bit too "manual" and low-level for my taste:
val fooGen = for (i <- Gen.choose(Int.MinValue, Int.MaxValue)) yield new Foo(i)
implicit def arbFoo: Arbitrary[Foo] = Arbitrary(fooGen)
Ideally, I would want a higher-order function where I just have to plug in an Int => Foo function.
I managed to cut it down to:
implicit def arbFoo = Arbitrary(Gen.resultOf((i: Int) => new Foo(i)))
But I still feel like there has got to be a slightly simpler way.
Well, you can use the underscore notation instead of defining the whole Foo-creating function as (i: Int) => new Foo(i)):
class Foo(i: Int)
(1 to 3).map(new Foo(_))
This works because Scala knows that Foo takes an Int, and that map is mapping over Ints, so there's no need to spell it all out explicitly.
So this is a bit shorter:
implicit def arbFoo = Arbitrary(Gen.resultOf(new Foo(_)))
Related
I have created MyList abstract class to implement the list, the reason for not using already present list implementation is I am learning Scala and this was exercise for the same course. I am writing a zipWith function to create a new list with concatenation of individual items for example:
list 1: list = [1,2,3]
list 2: listOfStrings = ["Hello", "This is", "Scala"]
and I am expecting output like: [1-Hello, 2-This is, 3-Scala]
I wrote zipWith function as mentioned below:
override def zipWith[B, C](list: MyList[B], zip: (A, B) => C): MyList[C] = {
if(list.isEmpty) throw new RuntimeException("Lists do not have the same length")
else new Cons(zip(h, list.head), t.zipWith(list.tail, zip))
}
And I am trying to call this function using this statement:
println(list.zipWith[String, String](listOfStrings, (Int,String)=>_+"-"+_))
But I am getting an error:
I could not infer the type of the parameter $3 of expanded function:
($3, _$4) => _$3 + "-" + _$4.
Type for this variable is clearly mentioned as Int still I am getting this error. This could be solved using:
println(list.zipWith[String, String](listOfStrings, _+"-"+_))
I am not able to understand why earlier statement fails, even after giving the type for the required variable
The syntax (Int,String)=>_+"-"+_ doesn't mean what you think.
It represents a function taking two parameters with some name but unknown type: (Int: ???, String: ???) => _+"-"+_.
Thus the compiler is raising an error because it indeed have no clue about the types.
You should either:
write it with explicit variable names: (i: Int, s: String) => s"$i-$s". (Notice the usage of interpolation which is recommended over adding int and string),
or declare the function separately like this: val f: (Int, String) => String = _+"-"+_.
I think the compiler is confused on which variable to match each underscore. This explicit expression works for me:
println(list.zipWith[String, String](listOfStrings, (a:Int, b:String) => a+"-"+b))
I have a functor to make a Heap module from a Comparable module, and a polymorphic function to apply Prim's algorithm to graphs with arbitrary labels. Ideally I'd like to be able to write something like:
let prim (graph: 'a graph)=
let module EdgeHeap=Heap.Make(
struct
type t='a edge
...
end
) in
...
let heap=EdgeHeap.create () in
...
but ocamlc says that 'a is unbound. How do I work around this?
Normally, you'd have prim (along with related functions) in a functor of its own that is parameterized over a graph module signature. I.e. something like:
module type GraphSpec = sig
type t
...
end
module GraphAlgorithms(G: GraphSpec) = struct
type graph = ...
module EdgeHeap = Heap.Make(struct
type t = G.t edge
...
end)
let prim (g: graph) = ...
let kruskal (g: graph) = ...
end
This avoids the use of type variables; instead, you pass the type through the GraphSpec functor argument.
But if you just need it for a single function, this may be overkill. You can work around it then by using locally abstract types. A simple example to illustrate how that works:
let min_list (type u) (l: u list) =
let module S = Set.Make(struct
type t = u
let compare = compare
end) in
S.of_list l |> S.min_elt
(I use OCaml version 4.02.3)
I defined a type self
# type self = Self of self;;
type self = Self of self
and its instance s
# let rec s = Self s;;
val s : self = Self <cycle>
Since OCaml is a strict language, I expected defining s will fall into infinite recursion. But the interpreter said s has a value and it is Self <cycle>.
I also applied a function to s.
# let f (s: self) = 1;;
val f : self -> int = <fun>
# f s;;
- : int = 1
It seems s is not evaluated before the function application (like in non-strict language).
How OCaml deal with cyclic data like s? Self <cycle> is a normal form?
OCaml is indeed an eager language, however s is a perfectly valid and fully evaluated term that happens to contain a cycle. For instance, this code yields the expected result:
let f (Self Self x) = x
f s == s;;
More precisely, the memory representation of constructors with at n arguments are boxed and read like this:
⋅—————————————————————————————————————————————⋅
| header | field[0] | field[1] | ⋯ | fiekd[n] |
⋅—————————————————————————————————————————————⋅
The header contains metadata whereas field[k] is an OCaml value, i.e. either an integer or a pointer. In the case of s, Self has only one argument, and thus only one field field[0]. The value of field[0] is then simply a pointer towards the start of the block. The term s is thus perfectly representable in OCaml.
Moreover, the toplevel printer is able to detect this kind of cycles and print an <cycle> to avoid falling into an infinite recursion when printing the value of s. Here, <cycle>, like <abstr> or <fun>, represents just a kind of value that the toplevel printer cannot print.
Note, however, that cyclical value will trigger infinite recursion in many situations, for instance f s = s where (=) is the structural equality
and not the physical one (i.e. (==)) triggers such recursion, another example would be
let rec ones = 1 :: ones;; (* prints [1;<cycle>] *)
let twos = List.map ((+) 1) ones;; (* falls in an infinite recursion *)
I would like to represent some scalar value (e.g. integers or strings)
by either it's real value or by some NA value and later store them
in a collection (e.g. a list). The purpose is to handle missing values.
To do this, I have implemented a signature
module type Scalar = sig
type t
type v = Value of t | NA
end
Now I have some polymorphic Vector type in mind that contains Scalars. Basically, some of the following
module Make_vector(S: Scalar) = struct
type t = S.v list
... rest of the functor ...
end
However, I cannot get this to work. I would like to do something like
module Int_vector = Make_vector(
struct
type t = int
end
)
module Str_vector = Make_vector(
struct
type t = string
end
)
... and so on for some types.
I have not yet worked a lot with OCaml so maybe this is not the right way. Any advises on how to realize such a polymorphic Scalar with a sum type?
The compiler always responds with the following message:
The parameter cannot be eliminated in the result type.
Please bind the argument to a module identifier.
Before, I have tried to implement Scalar as a sum type but ran into
complexity issues when realizing some features due to huge match clauses. Another (imo not so nice) option would be to use option. Is this a better strategy?
As far as I can see, you are structuring v as an input type to your functor, but you really want it to be an output type. Then when you apply the functor, you supply only the type t but not v. My suggestion is to move the definition of v into your implementation of Make_vector.
What are you trying to do exactly with modules / functors? Why simple 'a option list is not good enough? You can have functions operating on it, e.g.
let rec count_missing ?acc:(acc=0) = function
| None::tail -> count_missing ~acc:(acc+1) tail
| _::tail -> count_missing ~acc tail
| [] -> acc ;;
val count_missing : ?acc:int -> 'a option list -> int = <fun>
count_missing [None; Some 1; None; Some 2] ;;
- : int = 2
count_missing [Some "foo"; None; Some "bar"] ;;
- : int = 1
I have a large sum type originating in existing code. Let's say it looks like this:
type some_type =
| Variant1 of int
| Variant2 of int * string
Although both Variant1 and Variant2 are used elsewhere, I have a specific function that only operates on Variant2:
let print_the_string x =
match x with
| Variant2(a,s) -> print_string s; ()
| _ -> raise (Failure "this will never happen"); ()
Since this helper function is only called from one other place, it is easy to show that it will always be called with an input of Variant2, never with an input of Variant1.
Let's say the call looks like this:
let () =
print_the_string (Variant2(1, "hello\n"))
If Variant1 and Variant2 were separate types, I would expect OCaml to infer the type Variant2 -> () for print_the_string, however, since they are both variants of the same sum type, OCaml infers the signature some_type -> ().
When I encounter a program that throws an exception with a message like "this will never happen," I usually assume the original programmer did something wrong.
The current solution works, but it means that a mistake in the program would be caught at runtime, not as a compiler error as would be preferable.
Ideally, I'd like to be able to annotate the function like this:
let print_the_string (x : some_type.Variant2) =
But, of course, that's not allowed.
Question: Is there a way to cause a compiler error in any case where Variant1 was passed to print_the_string?
A related question was asked here, but nlucarioni and Thomas's answers simply address cleaner ways to handle incorrect calls. My goal is to have the program fail more obviously, not less.
Update: I'm accepting gallais's solution as, after playing with it, it seems like the cleanest way to implement something like this. Unfortunately, without a very messy wrapper, I don't believe any of the solutions work in the case where I cannot modify the original definition of some_type.
There is not enough information in your post to decide whether what follows could be useful for you. This approach is based on propagating an invariant and will play nicely if your code is invariant-respecting. Basically, if you do not have functions of type some_type -> some_type which turn values using Variant2 as their head constructor into ones constructed using Variant1 then you should be fine with this approach. Otherwise it gets pretty annoying pretty quickly.
Here we are going to encode the invariant "is built using Variant2" into the type by using
phantom types and defining some_type as a GADT. We start by declaring types whose sole purpose is to play the role of tags.
type variant2
type variantNot2
Now, we can use these types to record which constructor was used to produce a value of some_type. This is the GADT syntax in Ocaml; it's just slightly different from the ADT one in the sense that we can declare what the return type of a constructor is and different constructors can have different return types.
type _ some_type =
| Variant1 : int -> variantNot2 some_type
| Variant2 : int * string -> variant2 some_type
One could also throw in a couple of extra constructors as long as their signature records the fact their are not Variant2. I won't deal with them henceforth but you can try to extend the definitions given below so that they'll work well with these extra constructors. You can even add a print_the_second_int which will only take Variant3 and Variant4 as inputs to check that you get the idea behind this.
| Variant3 : int * int -> variantNot2 some_type
| Variant4 : float * int -> variantNot2 some_type
Now, the type of print_the_string can be extremely precise: we are only interested in elements of some_type which have been built using the constructor Variant2. In other words, the input of print_the_string should have type variant2 some_type. And the compiler can check statically that Variant2 is the only constructor possible for values of that type.
let print_the_string (x : variant2 some_type) : unit =
match x with Variant2 (_, s) -> print_string s
Ok. But what if we have a value of type 'a some_type because it was handed over to us by a client; we built it tossing a coin; etc.? Well, there's no magic there: if you want to use print_the_string, you need to make sure that this value has been built using a Variant2 constructor. You can either try to cast the value to a variant2 some_type one (but this may fail, hence the use of the option type):
let fromVariant2 : type a. a some_type -> (variant2 some_type) option = function
| Variant2 _ as x -> Some x
| Variant1 _ -> None
Or (even better!) decide in which realm the value lives:
type ('a, 'b) either = | Left of 'a | Right of 'b
let em : type a. a some_type -> (variant2 some_type, variantNot2 some_type) either =
fun x -> match x with
| Variant1 _ -> Right x
| Variant2 _ -> Left x
My solution would be to have print_the_string : int * string -> unit, since the Variant2 part provides no information you should drop it.
The type inference works toward inferring types (obviously) not values of types. But you can do what you propose with polymorphic variants. Although, I agree with Thomash.
type v1 = [ `Variant1 of int ]
type v2 = [ `Variant2 of int * string ]
let print_the_string (`Variant1 x) = ()
Gallais provided an excellent, but long answer, so I've decided to add a shorter version.
If you have a variant type and would like to add functions that works only on a subset of variants, then you can use GADTS. Consider the example:
open Core.Std
type _ t =
| Int: int -> int t
| Str: string -> string t
let str s = Str s
let uppercase (Str s) = Str (String.uppercase s)
Function uppercase has type string t -> string t and accepts only string version of type t, so you can deconstruct the variant just in place. Function str has type string -> string t, so that the return type carries in itself an information (a witness type) that the only possible variant, produced from this function is Str. So when you have a value that has such type, you can easily deconstruct it without using explicit pattern-matching, since it becomes irrefutable, i.e., it can't fail.