Issue inferring type for generic - crystal-lang

I have a c library that I bind to, which has many structs that hold data of different types.
#[Link("foo")]
lib LibFoo
struct IntStruct
data : LibC::Int
end
struct DoubleStruct
data : LibC::Double
end
fun get_int_struct(n : LibC::SizeT) : IntStruct*
fun get_double_struct(n : LibC::SizeT) : DoubleStruct*
end
I have a generic class where I want the type T to be the type of one of those structs, based off of an input array.
class GenericClass(T)
#ptr : Pointer(T)
#obj : T
def initialize(arr : Array)
#ptr = infer_type(arr)
#obj = #ptr.value
end
end
Where infer_type looks like:
def infer_type(data : Array(Int32))
return LibFoo.get_int_struct(data.size)
end
def infer_type(data : Array(Float64))
return LibFoo.get_double_struct(data.size)
end
The code works fine when I explicitly set the type...
GenericClass(LibFoo::IntStruct).new [1, 2, 3, 4, 5]
...but I would like to infer the type.

Maybe providing a custom generalized new method works for you?
struct A
end
struct B
end
class Generic(T)
def self.new(items : Array(A)) forall A
new(fetch_struct(items))
end
private def initialize(#struct : T)
end
private def self.fetch_struct(items : Array(Int32))
A.new
end
private def self.fetch_struct(items : Array(Float64))
B.new
end
end
p Generic.new([1])
p Generic.new([1.0])
https://carc.in/#/r/7s6d

Related

OCaml defining and implementing interface

Let's have such code
module type INTERFACE =
sig
val function_that_must_be_implemented : int -> int
end
module Implementation : INTERFACE =
struct
let function_that_must_be_implemented x = x
end
Is any way to describe the same thing but using OCaml classes? I want to have a class that implements such interface.
There is something called a class type:
class type interface = object method method_I_want : int end
Then you can implement it:
class implementation : interface = object
method method_I_want = 14
end
You can indeed instantiate this class:
# let abc = new implementation;;
val abc : implementation = <obj>
# abc#method_I_want;;
- : int = 14

Crystal method return multiple values

Can Crystal-lang method return multiple values with specific type?
I know that it can be implemented in this way:
def my_method(arg_1 : Int, arg_2 : String) : Tuple
return arg_1, arg_2
end
res_1, res_2 = my_method(1, "1")
but it also work if I do:
result = my_method(1, "1") #=> {1,"2"}
but can I do somethink like in Go-lang
def my_method(arg_1 : Int, arg_2 : String) : Int, String
return arg_1, arg_2
end
???
Thanks!
Crystal methods can only return one value. The way to "return multiple values" is by returning a tuple and then, if you want, immediately unpack it at the call site, like what you did.
If you want to specify the return type you can do:
def my_method(arg_1 : Int, arg_2 : String) : {Int32, String}
return arg_1, arg_2
end
Or (the same, just another syntax):
def my_method(arg_1 : Int, arg_2 : String) : Tuple(Int32, String)
return arg_1, arg_2
end
You can also use a shorter syntax to return multiple values:
def my_method(arg_1 : Int, arg_2 : String)
{arg_1, arg_2}
end
That is, doing return 1, 2 is internally the same as returning the tuple {1, 2}.
In the end, it doesn't really matter how this is implemented, maybe in Go the function doesn't really return two values but passes pointers or something like that, and then in assembly there aren't even functions, so what matters if you can return multiple things and then get them all at once, somehow.

type mismatch error declaring list of classes

def getValueAndItsType() : List[ (AnyRef, Class[_]) ] = {
val dataSet1 = ("some string data", classOf[String])
val dataSet2 = (new Thread(), classOf[Thread])
val dataSet3 = (new NullPointerException(), classOf[NullPointerException])
val dataSet4 = (5, classOf[Int])
val list = List(dataSet1, dataSet2, dataSet3, dataSet4)
list
}
Type type mismatch; found :
List[(Any, Class[_ >: Int with NullPointerException with Thread with
String])] required: List[(AnyRef, Class[_])]
If dataSet4 is removed from List, the compile time error disappears
Please suggest, what is wrong with Class[_]. Isn't it
equivalent to Class[?] in java ? I appreciate, if you also suggest
correct declaration for doing this..
In Scala:
Any is the root of the Scala class.
AnyRef is the root of the class of reference types, it extends from Any.
AnyVal is the root class of all value types. it extends from Any
Null is a subtype of all reference types.
Nothingis a subtype of all other types including Null
So base on your code, you need to extend from Any, include AnyRef: reference types and AnyVal: values types.
def getValueAndItsType() : List[ (Any, _ <: Any) ] = {
val dataSet1 = ("some string data", classOf[String])
val dataSet2 = (new Thread(), classOf[Thread])
val dataSet3 = (new NullPointerException(), classOf[NullPointerException])
val list = List(dataSet1, dataSet2, dataSet3)
list
}

Mutually recursive module and functor in OCaml

I have defined an interface A to be used by several functors, and notably by MyFunctor :
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
Now I want to define a module B with implements the interface A. In particular, the implementation of complex_func should use basic_func through complex_impl in MyFunctor :
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
However, this code doesn't compile as B is not fully declared in the context of MyFunctor(B). Obviously B depends on MyFunctor(B), which itself depends on B, so I tried to use the rec keyword on module B, but it didn't work out.
So, is it possible to do something like this ? It would be useful as I have several modules B_1, ..., B_n that use the same implementation of B_k.complex_func in terms of B_k.basic_func.
Or is there a better pattern for my problem ? I know that I can declare complex_impl as a regular function taking basic_func as a parameter, without using a functor at all :
let complex_impl basic_func params =
...
basic_func ...
...
But in my case complex_impl uses many basic functions of A, and I think that the paradigm of functors is clearer and less error-prone.
Edit : I followed this answer, but in fact, A uses some type t that is specialized in B :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
And now I get the error (for x at line Impl.complex_impl x) :
This expression has type t = int but an expression was expected of type B.t
Edit 2 : I solved this second problem with the following code :
module rec B :
A with type t = int
= struct
type t = int
...
end
You can use recursive modules just like you'd write recursive let bindings
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
Note (a) the module rec bit in the definition of B and (b) that I am required to provide a module signature for a recursive module definition.
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
There's a small caveat, however, in that this only works because the signature A has only values which are function types. It is thus known as a "safe module". If basic_func and complex_func were values instead of function types then it would fail upon compilation
Error: Cannot safely evaluate the definition
of the recursively-defined module B

Covariance and Scala Collections

I'm trying to get my head around the covariance of Scala's collections. I have the following:
abstract class MediaFormat{
def name:String
def status:String
}
case class H264_high(status:String="on") extends MediaFormat {
def name = "h264_high"
}
case class H264_med(status:String="on") extends MediaFormat {
def name = "h264_med"
}
case class H264_low(status:String="on") extends MediaFormat {
def name = "h264_low"
}
case class H264_syndication(status:String="off") extends MediaFormat {
def name = "h264_syndication"
}
What I wanted to do was have a set of all of these formats because I need a collection where each format only occurs once, so I tried:
object MediaFormat {
val allFormats:Set[MediaFormat] = Set(H264_high,H264_low)
}
This gave me a compile time exception because, as I now understand, Set is invariant.
So I think, well I guess I'll just have to use a List and manage the repeated values myself
but then I try this:
object MediaFormat {
val allFormats:List[MediaFormat] = List(H264_high,H264_low)
}
because as I understand it, List is covariant, but that still doesn't compile.
Can someone help me understand what I should do to get a collection of my formats?
It doesn't compile because you are referencing the companion object (module), not the case classes! The compile error (which you should have posted) is nothing to do with variance. It will work, with Set if you do this:
val allFormats: Set[MediaFormat] = Set(H264_high(), H264_low())
^^ ^^
Or alternatively;
val allFormats = Set[MediaFormat](H264_high(), H264_low())
However, it makes no sense for these to be case classes given your description of the problem; I would just make them modules, i.e.
case object H264_syndication extends MediaFormat {
def status = "off"
def name = "h264_syndication"
}
Then your original code will work just fine. Or I would make them vals as follows:
case class MediaFormat(status: String, name: String)
val H264_syndication = MediaFormat(status ="off", name = "h264_syndication")
I think this would be my preference; I rarely use abstract classes any more to be honest (normally, I am dishonest).
Explanation: Covariance means the following:
G[S] <: G[T] iff S <: T
The fact that Set is invariant, means that a Set[S] is not a subtype of Set[T] (for S <: T), but it does not mean that such a Set[T] may not contain elements of type S.