How can I hide methods in F#? - api

I am currently implementing a Spec framework in F# and I want to hide the Equals, GetHashCode etc. methods on my should type, so that the API is not cluttered with these.
I know in C# it is done by making the class implement an interface like this:
using System;
using System.ComponentModel;
public interface IFluentInterface
{
[EditorBrowsable(EditorBrowsableState.Never)]
bool Equals(object other);
[EditorBrowsable(EditorBrowsableState.Never)]
string ToString();
[EditorBrowsable(EditorBrowsableState.Never)]
int GetHashCode();
[EditorBrowsable(EditorBrowsableState.Never)]
Type GetType();
}
I tried doing the same in F#:
type IFluentInterface = interface
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract Equals : (obj) -> bool
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract ToString: unit -> string
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetHashCode: unit -> int
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetType : unit -> Type
end
Implemented it in my type:
interface IFluentInterface with
member x.Equals(other) = x.Equals(other)
member x.ToString() = x.ToString()
member x.GetHashCode() = x.GetHashCode()
member x.GetType() = x.GetType()
but without success.
I also tried to override the methods in my type and adding the attribute that way, but that didn't do the trick either.
So the question remains, how can I clean up my API ?
Edit:
Thanks to the help (see below) I was able to solve my problem.
In summary, .Equals and .GetHashCode can be hidden via [<NoEquality>] [<NoComparison>] but that will also change the semantics.
The hiding via EditorBrowsable attributes does not work.
The only way to have a clean API and still be able to overload methods is to make these method members static.
The resulting class can be found by browsing inside my project FSharpSpec.
The type in question can be found here.
Thanks to everyone who helped me solve this problem.
Cheers ...

Alternatively, you could design the library using an alternative style using functions enclosed in a module. This is the usual way for writing functional code in F# and then you won't need to hide any standard .NET methods. To complete the example given by 'kvb', here is an example of object-oriented solution:
type MyNum(n:int) =
member x.Add(m) = MyNum(n+m)
member x.Mul(m) = MyNum(n*m)
let n = new MyNum(1)
n.Add(2).Mul(10) // 'ToString' shows in the IntelliSense
The functional way of writing the code might look like this:
type Num = Num of int
module MyNum =
let create n = Num n
let add m (Num n) = Num (m + n)
let mul m (Num n) = Num (m * n)
MyNum.create 1 |> MyNum.add 2 |> MyNum.mul 10
If you type MyNum., the F# IntelliSense will show the functions defined in the module, so you won't see any noise in this case.

Repeating my answer from
http://cs.hubfs.net/forums/thread/13317.aspx
In F# you can disallow Equals & GetHashCode (and remove them from intellisense) by annotating the type with the NoEquality and NoComparison attributes, as shown below. User-defined methods can also be hidden from the intellisense list via the Obsolete attribute or the CompilerMessage attribute with IsHidden=true. There is no way to hide the System.Object methods GetType and ToString from the F# intellisense.
[<NoEquality; NoComparison>]
type Foo() =
member x.Bar() = ()
member x.Qux() = ()
[<System.Obsolete>]
member x.HideMe() = ()
[<CompilerMessage("A warning message",99999,IsError=false,IsHidden=true)>]
member x.WarnMe() = ()
let foo = new Foo()
foo. // see intellisense here

I don't think that there is any way to do that in F# in general. In the particular case of .Equals and .GetHashCode, you can make them unusable by putting a [<NoEquality>] attribute on your type, but this actually has a semantic effect in addition to hiding those methods.
EDIT
It might also be worth mentioning that fluent interfaces are rarely used in F#, since it's much more idiomatic to use combinators and pipelining instead. For instance, imagine that we want to create a way to create arithmetic expressions. Rather than
let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)
I think that most F# users would prefer to write
open Expressions
let x =
1
|> makeExpr
|> add 2
|> mul 3
|> add 4
With this style, there's no need to hide members because expressions get piped to combinators, rather than calling methods of an expression builder.

Related

Specifying a function with templates that takes and returns an arbitrary class

I'm interested in defining a function that given a class variable, generates and a new instance of the class object with a randomly selected member attribute mutated.
Context: Consider an instance, circle1, of some class, Circle, has attributes color and radius. These attributes are assigned values of red and 5, respectively. The function in question, mutate, must accept circle1 as an argument, but reject non-class arguments.
For other data types, templates provide an answer in this context. That is, templates may be used to specify generic instances of functions that can accept arguments of multiple types.
How can a generic function that accepts (and returns) an instance of any class be defined using templates?
In general, if you need to restrict what a template can take, you use template constraints. e.g.
import std.traits : isIntegral;
auto foo(T)(T t)
if(isIntegeral!T)
{
...
}
or
import std.functional : binaryFun;
auto foo(alias pred, T, U)(T t, U u)
if(is(typeof(binaryFun!pred(t, u.bar())) == bool)
{
...
}
As long the condition can be checked at compile time, you can test pretty much anything. And it can be used for function overloading as well (e.g. std.algorithm.searching.find has quite a few overloads all of which are differentiated by template constraint). The built-in __traits, the eponymous templates in std.traits, and is expressions provide quite a few tools for testing stuff at compile time and then using that information in template constraints or static if conditions.
If you specifically want to test whether something is a class, then use an is expression with == class. e.g.
auto foo(T)(T t)
if(is(T == class))
{
...
}
In general though, you'll probably want to use more specific conditions such as __traits(compiles, MyType result = t.foo(22)) or is(typeof(t.foo(22)) == MyType). So, you could have something like
auto mutate(T)(T t)
if(is(T == class) &&
__traits(compiles, t.color = red) &&
__traits(compiles, t.radius = 5))
{
...
}
If the condition is something that you want to reuse, then it can make sense to create an eponymous template - which is what's done in Phobos in places like std.range.primitives and std.range.traits. For instance, to test for an input range, std.range.primitives.isInputRange looks something like
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = R.init; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
Then code that requires an input range can use that. So, lots of functions in Phobos have stuff like
auto foo(R)(R range)
if(isInputRange!R)
{
...
}
A more concrete example would be this overload of find:
InputRange find(alias pred = "a == b", InputRange, Element)
(InputRange haystack, Element needle)
if(isInputRange!InputRange &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{
...
}
Ali Çehreli's book, Programming in D, has several relevant chapters, including:
http://ddili.org/ders/d.en/templates.html
http://ddili.org/ders/d.en/cond_comp.html
http://ddili.org/ders/d.en/is_expr.html
http://ddili.org/ders/d.en/templates_more.html

Is there a Rust equivalent to `dynamic` in C#?

Can the following C# code be translated to Rust?
dynamic x = 109;
x = "Hi";
I'm asking for a general dynamic type to allow creating an array of dynamic values. For example:
var l = new dynamic[2];
l[0] = 102;
l[1] = "Hi";
One option is to use a vector of Any (link to beta because the stable docs is not showing the methods defined for Any, but they are stable):
use std::any::Any;
fn main() {
let mut v: Vec<Box<Any>> = vec![];
v.push(Box::new(102usize));
v.push(Box::new("Hi"));
for item in &v {
// to do an operation, it is necessary to downcast to
// a concrete type
if let Some(x) = item.downcast_ref::<usize>() {
println!("num = {:?}", x)
}
}
}
Note that, contrary to dynamic in C#, that is assumed to support any operation, a value of type Any (Box<Any>) only support the operations defined in Any (Box<Any> and Any). A downcast is necessary to call any method of the concrete type.
I think that it is not possible to have a type like dynamic of C# in Rust. To support calling any method on a dynamic value, it is necessary to have (complete) runtime reflection support, and Rust does not provide it.
If you know the methods that will be called, then the best option is to define a trait and use Box<Trait> (Any is not necessary in this case).
Not directly. You can just create a new binding for x:
fn main() {
let x = 109;
let x = "Hi";
}
Depending on your use case, you might be able to use a generic bounded by a trait or a trait object to achieve similar goals:
use std::fmt::Display;
fn main() {
let mut x: Box<Display> = Box::new(109);
x = Box::new("Hi");
}
However, the C# docs state:
At compile time, an element that is typed as dynamic is assumed to support any operation.
This is not true for a trait object; a trait object only can be used for the explicit methods in the trait. I have not found this to be a significant hurdle in the code I have written. Generally, there's a fixed number of methods that I want to call so it's possible to map those to a trait. In other cases, I can provide a generic type to allow the user to specify a type that fits their case.

F# Object constructor

After recently picking up a bit of C# after a long time of F#, I came to realise that 'object constructors' are a nice way of tricking oneself into believing they are dealing with a functional object.
Consider:
let x = new Something()
x.Key <- 1
x.Value <- 2
This feels very unclean because of the very obvious mutation of values. Especially if we keep our objects write once, it feels very unnecessary In C#, it is possible to initialise the object like this:
var x = new Something() { Key = 1, Value = 2 };
This looks nicer and actually it felt like I was using a record (almost), obviously its just sugar but its nice sugar.
Q. Assuming we have no control over `Something' (pretend its from some C# library), is it possible, in F# to use this shorthand initialisation, if not, why?
Yes, you can do that. It would look something like this:
let x = new Something(Key = 1, Value = 2)
The syntax is detailed in Constructors (F#) under the section "Assigning Values to Properties at Initialization".
Yes, F# support use cases similar to C# object initializers but F# approach is somewhat more generic.
F# specification 14.4 Method Application Resolution says:
(after method is successfully resolved) Build the resulting elaborated expression by following these steps:
For each NamedActualArgs whose target is a settable property or field, assign the value into the
property.
meaning that you can do things that C# doesn't allow
type Something() =
member val Key = 0 with get,set
member val Value = "" with get,set
static member Create() = Something()
let a = Something(Key = 1, Value = "1") // create instance with constructor, set properties afterwards
let b = Something.Create(Key = 1, Value = "1") // create instance using factory method, set properties afterwards

Scala class inheritance

Tagged as homework.
I'm having trouble in the object oriented world while trying to implement a class.
I'm implenting various functions to take action on lists, that I'm using to mock a set.
I'm not too worried about my logic on how to find union, for example, but really just the structure.
For eg:
abstract class parentSet[T] protected () {
def union(other:parentSet[T]):parentSet[T]
}
Now I want a new class extending parentSet:
class childSet[T] private (l: List[T]) extends parentSet[T] {
def this() = this(List())
private val elems = l
val toList = List[T] => new List(l)
def union(other:parentSet[T]):childSet[T] = {
for (i <- this.toList) {
if (other contains i) {}
else {l :: i}
}
return l
}
}
Upon compiling, I receive errors such that type childSet isn't found in def union, nor is type T to keep it parametric. Also, I assume my toList isn't correct as it complains that it isn't a member of the object; to name a few.
Where in my syntax am I wrong?
EDIT
Now I've got that figured out:
def U(other:parentSet[T]):childSet[T] = {
var w = other.toList
for (i <- this.toList) {
if (!(other contains i)) {w = i::w}
}
return new childSet(w)
}
Now, I'm trying to do the same operations with map, and this is what I'm working on/with:
def U(other:parentSet[T]):MapSet[T] = {
var a = Map[T,Unit]
for (i <- this.toList) {
if (!(other contains i)) {a = a + (i->())}
}
return new MapSet(elems + (a->()))
}
I still want to use toList to make it easily traversable, but I'm still getting type errors while messing with maps..
This code has a few problems:
It seems that you are not realizing that List[T] is an immutable type, meaning you cannot change its value once created. So if you have a List[T] and you call the :: method to prepend a value, the function returns a new list and leaves your existing one unchanged. Scala has mutable collections such as ListBuffer which may behave more like you expect. So when you return l, you're actually returning the original list.
Also, you have the order wrong in using ::. It should go i :: l, since :: is a right-binding function (because it ends with a :).
Lastly, in your union method you are doing (other contains i). Maybe it's just the Scala syntax that's confusing you, but this is the same as doing (other.contains(i)) and clearly contains is not a defined method of parentSet. It is a method on the List[T] type, but you're not calling contains on a list.
You tagged this as homework so I'm not going to fix your code, but I think you should
Look at some examples of correct Scala code involving lists, try here for starters
Play around in the Scala REPL and try creating and working with some lists, so you get a feel for how immutable collections work.
To answer your direct question, even though childSet is inheriting parentSet the original method specify parentSet as the return type and not childSet. You can either only use parentSet as the type OR you could specify the return type to be anything that inherits parentSet.

Why is method overloading not defined for different return types?

In Scala, you can overload a method by having methods that share a common name, but which either have different arities or different parameter types. I was wondering why this wasn't also extended to the return type of a method? Consider the following code:
class C {
def m: Int = 42
def m: String = "forty two"
}
val c = new C
val i: Int = C.m
val s: String = C.m
Is there a reason why this shouldn't work?
Thank you,
Vincent.
Actually, you can make it work by the magic of 'implicit'. As following:
scala> case class Result(i: Int,s: String)
scala> class C {
| def m: Result = Result(42,"forty two")
| }
scala> implicit def res2int(res: Result) = res.i
scala> implicit def res2str(res: Result) = res.s
scala> val c = new C
scala> val i: Int = c.m
i: Int = 42
scala> val s: String = c.m
s: String = forty two
scala>
You can of course have overloading for methods which differ by return type, just not for methods which differ only by return type. For example, this is fine:
def foo(s: String) : String = s + "Hello"
def foo(i: Int) : Int = i + 1
That aside, the answer to your question is evidently that it was a design decision: the return type is part of the method signature as anyone who has experienced an AbstractMethodError can tell you.
Consider however how allowing such overloading might work in tandem with sub-typing:
class A {
def foo: Int = 1
}
val a: A = //...lookup an A
val b = a.foo
This is perfectly valid code of course and javac would uniquely resolve the method call. But what if I subclass A as follows:
class B extends A {
def foo: String = "Hello"
}
This causes the original code's resolution of which method is being called to be broken. What should b be? I have logically broken some existing code by subtyping some existing class, even though I have not changed either that code or that class.
The main reason is complexity issues: with a "normal" compiler approach, you go inside-out (from the inner expression to the outer scope), building your binary step by step; if you add return-type-only differentiation, you need to change to a backtracking approach, which greatly increases compile time, compiler complexity (= bugs!).
Also, if you return a subtype or a type that can be automatically converted to the other, which method should you choose? You'd give ambiguity errors for perfectly valid code.
Not worth the trouble.
All in all, you can easily refactor your code to avoid return-type-only overload, for example by adding a dummy parameter of the type you want to return.
I've never used scala, so someone whack me on the head if I'm wrong here, but this is my take.
Say you have two methods whose signatures differ only by return type.
If you're calling that method, how does the compiler (interpreter?) know which method you actually want to be calling?
I'm sure in some situations it might be able to figure it out, but what if, for example, one of your return types is a subclass of the other? It's not always easy.
Java doesn't allow overloading of return types, and since scala is built on the java JVM, it's probably just a java limitation.
(Edit)
Note that Covariant returns are a different issue. When overriding a method, you can choose to return a subclass of the class you're supposed to be returning, but cannot choose an unrelated class to return.
In order to differentiate between different function with the same name and argument types, but different return types, some syntax is required, or analysis of the site of an expression.
Scala is an expression oriented language (every statement is an expression). Generally expression oriented languages prefer to have the semantics of expressions to be dependent only on the scope evaluation occurs in, not what happens to the result, so for the expression foo() in i_take_an_int( foo() ) and i_take_any_type ( foo()) and foo() as a statement all call the same version of foo().
There's also the issue that adding overloading by return type to a language with type inference will make the code completely incomprehensible - you'd have to keep an incredible amount of the system in mind in order to predict what will happen when code gets executed.
All answers that say the JVM does not allow this are straight up wrong. You can overload based on return type. Surprisingly, the JVM does allow this; it's the compilers for languages that run on the JVM that don't allow this. But there are ways to get around compiler limitations in Scala.
For example, consider the following snippet of code:
object Overload{
def foo(xs: String*) = "foo"
def foo(xs: Int*) = "bar"
}
This will throw a compiler error (Because varargs, indicated by the * after the argument type, type erase to Seq):
Error:(217, 11) double definition:
def foo(xs: String*): String at line 216 and
def foo(xs: Any*): String at line 217
have same type after erasure: (xs: Seq)String
def foo(xs: Any*) = "bar";
However, if you change value of the second foo to 3 instead of bar (that way changing the return type from String to Int) as follows:
object Overload{
def foo(xs: String*) = "foo"
def foo(xs: Int*) = 3
}
... you won't get a compiler error.
So you can do something like this:
val x: String = Overload.foo()
val y: Int = Overload.foo()
println(x)
println(y)
And it will print out:
3
foo
However, the caveat to this method is having to add varargs as the last (or only) argument for the overloaded functions, each with with their own distinct type.
Source: http://www.drmaciver.com/2008/08/a-curious-fact-about-overloading-in-scala/