OCaml types with different levels of specificity - interface

I am attempting to simulate an interface in OCaml and am using the "type" construct. I have two types:
type fooSansBar = {a: string; b: int};;
type fooConBar = {a:string; b:int; bar:char};;
...and would like to define a particular fooSansBar:
let fsb = {a="a"; b=3};;
...but am told that the bar field is not defined. From this, it appears that, contrary to the values I passed in matching fooSansBar's signature, the system believes I am trying to create a fooConBar. Is it possible to create a fooSansBar if the two types as defined above exist?
Additionally (because I'm new to OCaml) is there a better way to simulate an interface?

In OCaml, field names in record types must be unique, so the two types you define cannot coexist simultaneously. Caml is the only language I know with this property.
Because the second definition hides the first, when the compiler sees the a and b fields it expects them to belong to the fooConBar type and so complains of the missing bar field.
If you are trying to simulate an interface, the correct functional way to do it in Caml is to define a module type.
module type FOO_CON_BAR = sig
val a : string
val b : int
val bar : char
end
And an instance:
module Example = struct
let a = "hello"
let b = 99
let c = '\n'
end
With modules and module types you also get subtyping; there's no need to resort to objects.
P.S. My Caml is rusty; syntax may be off.

There are several possible solutions in OCaml depending how you're using the code you gave. The simplest is to combine the two types:
type fooBar = { a: string; b: int; bar: char option }
Another solution is to replace the records with objects because objects support subtyping (and can have their types inferred so there is no need to declare a type!):
# let fsb = object
method a = "a"
method b = 3
end;;
val fsb : < a : string; b : int > = <obj>
# fsb#a, fsb#b;;
- : string * int = ("a", 3)

The second type redefines a and b, effectively hiding the first, which is why it cannot be constructed any more. You could define these types in different modules, but that would be the same as using a different name for a and b.
These constructs can only be used when you do not try to "derive" from another interface, but just implement it.
If you wish to use these object oriented concepts in Ocaml, you could look at the object system, or, depending on your problem, the module system. Alternatively, you could try to solve your problem in a functional way. What problem are you trying to solve?

OCaml provides two ways to implement interfaces. One, as already mentioned, is a module type.
The other is a class type. You can write a class type (interface) fooSansBar:
class type fooSansBar = object
method a: string
method b: int
end
and a class type fooConBar:
class type fooConBar = object
inherit fooSansBar
method bar: char
end
This will allow you to use a fooConBar anywhere a fooSansBar is required. You can now create a fooSansBar, using type inference:
let fsb = object
method a = "a"
method b = 3
end
Now, fsb's type happens to be <a: string; b: int>, as indicated by Jon, but it's perfectly usable as a fooSansBar due to OCaml's structural subtyping.

In OCaml, it's not possible to have two record types with intersecting field sets present in the same scope.
If you really need to use record types with intersecting field sets, then you can work around this restriction by enclosing the types within their own dedicated modules:
module FooSansBar = struct type t = {a:string; b:int} end
module FooConBar = struct type t = {a:string; b:int; bar:char} end
Then you can construct instances of these types like so:
let fsb = {FooSansBar.a="a"; b=3}
let fcb = {FooConBar.a="a"; b=4; bar='c'}
These instances have the following types:
fsb : FooSansBar.t
fcb : FooConBar.t

Related

Generic class wrapper in scala

Hello I would like to create a generic wrapper in scala in order to track the changes of the value of any type. I don't know/haven't found any other ways so far and I was thinking of creating a class and I've been trying to use the Dynamic but it has some limitations.
case class Wrapper[T](value: T) extends Dynamic {
private val valueClass = value.getClass
def applyDynamic(id: String)(parameters: Any*) = {
val objectParameters = parameters map (x => x.asInstanceOf[Object])
val parameterClasses = objectParameters map (_.getClass)
val method = valueClass.getMethod(id, parameterClasses:_*)
val res = method.invoke(value, objectParameters:_*)
// TODO: Logic that will eventually create some kind of event about the method invoked.
new Wrapper(res)
}
}
With this code I have trouble when invoking the plus("+") method on two Integers and I don't understand why. Isn't there a "+" method in the Int class? The error I am getting when I try addition with both a type of Wrapper/Int is:
var wrapped1 = Wrapper(1)
wrapped1 = wrapped1 + Wrapper[2] // or just 2
type mismatch;
found : Wrapper[Int]/Int
required: String
Why is it expecting a string?
If possible it would also be nice to be able to work with both the Wrapper[T] and the T methods seamlessly, e.g.
val a = Wrapper[Int](1)
val b = Wrapper[Int](2)
val c = 3
a + b // Wrapper[Int].+(Wrapper[Int])
a + c // Wrapper[Int].+(Int)
c + a // Int.+(Wrapper[Int])
Well, if youre trying to make a proxy which will get any changes of desired values you'l probably fail without agents(https://dzone.com/articles/java-agent-1) because it will force you make code modifications for bytecode that accepts final classes and primitives to accept your proxy instead of that and it would require more than intercepting changes of "just class" but also all classes of members and produce origin-of-value analysis and so on. It's by no way trivial problem.
Another approach is to produce diffs of case classes by comparing classes in certain points of execution and there's generic implementation like that, it uses derivation for computing diffs: https://github.com/ivan71kmayshan27/ShapelesDerivationExample I believe you can came with easier solution with magnolia. Actualy this one is unable to work for just classes unless you write your own macro and have some problems regarding ordered and unordered collections.

Trying to keep types unwrapped when using refined

I am trying to use refined to create smart constructors based on primitives and avoid wrapping since same types might be used in large collections. Am I doing this right? Seems to work but a bit boilerplaty
type ONE_Pred = = MatchesRegex[W....
type ONE = String ## ONE_Pred
type TWO_Pred = OneOf[...
type TWO = String ## TWO_PRED
and then
case class C(one:ONE, two:TWO)
object C {
def apply(one:String, two:String):Either[String, C] =
(
refineT[ONE_Pred](one),
refineT[TWO_Pred](two)
).mapN(C.apply)
}
Refined has a mechanism for creating a companion-like objects that have some utilites already defined:
type ONE = String ## MatchesRegex["\\d+"]
object ONE extends RefinedTypeOps[ONE, String]
Note that:
You don't need a predicate type to be mentioned separately
It works for both shapeless tags and refined own newtypes. The flavor you get is based on the structure of type ONE.
You get:
ONE("literal") as alternative to refineMT/refineMV
ONE.from(string) as alternative to refineT/refineV
ONE.unapply so you can do string match { case ONE(taggedValue) => ... }
ONE.unsafeFrom for when your only option is to throw an exception.
With these "companions", it's possible to write much simpler code with no need to mention any predicate types:
object C {
def apply(one: String, two: String): Either[String, C] =
(ONE.from(one), TWO.from(two)).mapN(C.apply)
}
(example in scastie, using 2.13 with native literal types)

Records with similar fields in OCaml

In this answer, the suggested way of "attaching" meta information to types was using a record:
type _foo = ...
and foo = {n:_foo; m:meta}
but what if I have multiple types I'd like to wrap with meta information? Apparently all field names in record types must have different names, and writing:
type _foo = ...
and foo = {n:_foo; m:meta}
...
type _fooX = ...
and fooX = {nX:_fooX; mX:meta}
seems redundant :/. Classes are the only way to solve this? I'd like to avoid dealing with classes, if possible.
You can use parameterized type, perhaps.
type 'a wrapped = { base: 'a; extra: meta }
Jeffrey's solution is correct and scales perfectly to recursive types.
type location
type 'a loc = { a : 'a; loc : location }
type exp = Int of int | Add of exp loc * exp loc
It is still possible to use the previous two-time definition of your type,
as follows:
type exp_data = Int of int | Add of exp * exp
and exp = exp_data loc
Finally, a slightly different style is to use "open recursion", that is to define only an "derecursified type" open_exp with free parameters instead of recursive occurences. You can then get the recursive type back by taking the fixpoint; you can take different fixpoint, one with no additional information, and one with location interleaved for example. This is a generic construction to insert information at recursion sites, and its term-level counterpart allows for weaving different things in a recursive function (memoization, profiling, debug, etc.).
type 'e open_exp = Int | Add of 'e * 'e
type simple_exp = Simple of simple_exp open_exp
type located_exp = Loc of located_exp loc open_exp

Creating and using a generic function in a non generic F# interface

It is beyond me at this point. I'm trying to create an interface that looks something like
this.
type IFetchData =
abstract FetchData: string -> seq<'a>
The above declaration is valid (and compiles) but when I go to use it I get a compile time error. This expression was expected to have type 'a but here has type "what I'm currently trying to return" i.e. seq.
My example usage however looks like the following:
type SampleFetchData() =
interface IFetchData with
member self.FetchData str =
seq {
for letter in str do
yield letter // compile error here
}
I'm not sure what I'm doing wrong. All I'd like to do is allow the interface implementer to be able to write any function that returns a generic sequence either seq<string>,seq<int>,seq<record type here>, seq<union type here>, etc.
Can someone tell me what I'm missing here?
Thanks.
If you're loading the interface implementation using Reflection, then it is going to be quite difficult to work with it. The problem is that you get an object of type obj. You know that it implements IFetchData<'T> for some 'T, but statically, you don't know for which 'T. This is a problem because you can't cast the object to any more specific type - if you tried using IFetchData<obj>, it wouldn't work because you can't cast, for example, IFetchData<int> to that type.
I would recommend using a non-generic interface, which is quite common .NET pattern:
type IFetchDataUntyped =
abstract FetchData : string -> System.Collections.IEnumerable
type IFetchData<'T> =
inherit IFetchDataUntyped
abstract FetchData : string -> seq<'T>
When you load an implementation using Reflection, you can cast the object to IFetchDataUntyped and work with it in a fairly reasonable way (using Seq.cast to convert the sequence to a more specific type if you know the element type).
Depending on your application, you may also just make the FetchData method a generic method and keep the interface non-generic. Then you could cast dynamically loaded objects to the interface and invoke the method. However, this changes the design (because the method has to work for any type it gets as a type parameter):
type IFetchData =
abstract FetchData<'T> : string -> seq<'T> // Note: Generic parameter here!
You need to do something like
type IFetchData<'a> =
abstract FetchData: string -> seq<'a>
type SampleFetchData() =
interface IFetchData<char> with
member self.FetchData str =
seq {
for letter in str do
yield letter
}
i.e. the interface needs to be made generic. If you want to avoid the genericness you could use some inline constraints, rather than an interface
EDIT: Inline magic version
let inline Fetchdata string obj=
(^a: (member FetchData: string -> seq<'b> )(obj, string))
type SampleFetchData() =
member self.FetchData str =
seq {
for letter in str do
yield letter
}
Fetchdata "hello" (new SampleFetchData())

Implement equality outside type definition

I have several types that implement an interface. Equality for these types only depends on interface members. Is it possible to define equality for these types once, without overriding Equals or op_Equality for each type?
EDIT
I tried the following, but, for whatever reason, it overrode every use of =, even for types not implementing IEntity.
[<AutoOpen>]
module Equality =
let inline op_Equality (left:IEntity) (right:IEntity) = true
I also tried using flexible types (#IEntity). Same result.
What you're trying to do is something that mixins or typeclasses might enable in other languages; unfortunately there isn't equivalent functionality in F#. Your best bet is probably one of the following options:
Use an abstract base class instead of an interface.
Write your equality method outside of your type and then have all of your implementations defer to it. For example,
let entityEquals (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
i1.Member2 = i2.Member2 &&
...
type MyEntity() =
interface IEntity with
member x.Member1 = ...
...
override x.Equals(y) =
match y with
| :? IEntity as y -> entityEquals x y
| _ -> false
override x.GetHashCode() =
...
In addition to a bit of boilerplate, the downside here is that if anyone else implements your IEntity interface, they aren't forced to use your equality method - it's opt-in.
Create an another operator which you use for equality testing of IEntitys:
let (==) (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
...
The (huge) downside of this is that structural equality of types containing IEntitys (such as tuples, records, etc.) won't use this operator to compare those components, which is likely to lead to surprising broken code.
I don't think there is a way to do this in a static way. The problem is that extension members (e.g. if you added op_Equality as an extension) are ignored by static member constraints (e.g. if you also redefined = using inlin with op_Equality requirement).
The F# compiler has some special powers available only when compiling FSharp.Core.dll that could help (search sources for the declaration let inline GenericOne). It uses something like static type switch - but this cannot be accessed by mere mortals.
So, I don't have any idea better than using dynamic type test, which isn't really a good approach and it's probably better to define a custom operator for comparison of your interfaces.
For a reference, the ugly dynamic approach would be:
let inline (=) a b =
match a, b with
| :? IFoo as a, :? IFoo as b -> yourEquals a b
| _ -> a = b