Why does F# compiler prefer to generate closed implementations of FSharpFunc types? - f#

For this code:
module Module =
let func x y z = 0
[<EntryPoint>]
let main args =
func 1
func 1 1
0
Decompilation yields:
[CompilationMapping(SourceConstructFlags.Module)]
public static class Main
{
[CompilationMapping(SourceConstructFlags.Module)]
public static class Module
{
[Serializable]
internal sealed class main#30 : OptimizedClosures.FSharpFunc<object, object, int>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int x;
[CompilerGenerated]
[DebuggerNonUserCode]
internal main#30(int x)
{
this.x = x;
}
public override int Invoke(object y, object z)
{
return func(x, y, z);
}
}
[Serializable]
internal sealed class main#31-1 : FSharpFunc<object, int>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int x;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int y;
[CompilerGenerated]
[DebuggerNonUserCode]
internal main#31-1(int x, int y)
{
this.x = x;
this.y = y;
}
public override int Invoke(object z)
{
return func(x, y, z);
}
}
[CompilationArgumentCounts(new int[]
{
1,
1,
1
})]
public static int func<a, b, c>(a x, b y, c z)
{
return 0;
}
[EntryPoint]
public static int main(string[] args)
{
int x = 1;
new main#30(x);
int x2 = 1;
int y = 1;
new main#31-1(x2, y);
return 0;
}
}
public static a Dump<a>(a arg00)
{
return arg00.Dump();
}
}
It generates a concrete type, that is generic parameters are provided at type definition. Why is not this done at the point of construction? I also noticed that types are generated in the module where call occurs, not where func is defined.
Having let func x y z = ... we need implementations of types to cover all possibilities:
FSharpFunc<T1,FSharpFunc<T2,T3,TReturn>>
FSharpFunc<T1,T2,FSharpFunc<T3,TReturn>>
FSharpFunc<T1,FSharpFunc<T2,FsharpFunc<T3,TReturn>>>
Compiler could generate all possible combinations in the same place, where function is defined, closing only for parameters with inferenced types.
You could argue that for the list of 7 args the set of types going to be quite large, but types like FSharpFunc<T1,T2,..,Tn, FSharpFunc<...>> are a mere optimazation. And FSharpFunc supports up to six generic types, then compiler has to switch to FSharpFun<T1,T2,T3,T4,T5,FSharp<...>>.

As pointed out by Fyodor it's not function creation that makes the compiler generating the hidden classes. The hidden classes are used to implement partial application.
In F# a partial application and lambdas are implemented as a compiler generated class that extends an abstract class. C# lambdas rely on delegates instead. IIRC Java and Scala use a similar technique to F# as JVM doesn't have delegates.
I suspect the F# compiler generates a class per partial application because it's simpler than collecting all partial applications and coalesce the identical ones.
It also helps the debuggability of F# programs as the name hints where the partial application was done: main#31-1 => In the main function at row 31. This name if included in logs or performance runs can help identifying what partial application is causing problems.
This comes at the cost of increasing the size of the F# assembly file as noted in a comment by Pavel.

Related

Dart abstract static method

I want to create an abstract Sort class for my class project using dart which I will extend with Sorting algorithm classes like MergeSort, QuickSort, Heap, etc. I wrote the below code but I cannot create an abstract static sort method which I can override and use like
Heap.sort(arr)
OR
MergeSort.sort(arr)
Do anyone know why I cannot create abstract static method and also if you have any other way of doing this please feel free to guide me :D
abstract class Sort {
// void sort(List array);
static void sort(List array);
bool isSorted(List array) {
for (int i = 0; array.length > i - 1; i++) {
if (array[i] > array[i + 1]) {
return false;
}
}
return true;
}
void swap(arr, i, j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
As the answer linked above says, you can't have abstract static methods.
An abstract method does just one thing, it adds a method signature to the interface of the class, which other (non-abstract) classes implementing the interface then has to provide an implementation for. The abstract method doesn't add implementation.
Static methods are not part of the interface, so being abstract and static means it has no effect at all. It's a method with no implementation, which nobody can ever implement. So you're not allowed to do that.
To actually have separate classes representing different sorting algorithms, just do that directly using instance methods. That's the strategy object pattern.
abstract class Sorter<T> {
void sort(List<T> values);
int compare(T value1, T value2);
void swap(List<T> values, int index1, int index2) {
T tmp = values[index1];
values[index1] = values[index2];
values[index2] = tmp;
}
}
abstract class HeapSort<T> extends Sorter<T> {
void sort(List<T> values) {
// heap sort algorithm.
}
}
abstract class MergeSort<T> extends Sorter<T> {
void sort(List<T> values) {
// merge sort algorithm.
}
}
mixin ComparableSorter<T extends Comparable<T>> on Sorter<T> {
int compare(T value1, T value2) => value1.compareTo(value2);
}
class ComparableHeapSort<T extends Comparable<T>>
extends HeapSort<T> with ComparableSorter<T> {}
class CustomCompareHeapSort<T> extends HeapSort<T> {
int Function(T, T) _compare;
CustomCompareHeapSort(int Function(T, T) compare) : _compare = compare;
int compare(T value1, T value2) => _compare(value1, value2);
}
There are plenty of options about how to slice the API and abstract over different parts of it.
I recommend figuring out what use-cases you want to support, before starting the API design.

Instantiating a subclass in a superclass?

abstract class A {
A(this.x, this.y);
// error: abstract classes cannot be instantiated
//
// another issue: even if you used a base concrete class
// to perform this operation, it would lose type information.
A copy({int? x, int? y}) => A(x ?? this.x, y ?? this.y);
final int x;
final int y;
}
class B extends A {
// Forced to implement copy and similar
// methods on all classes that extend A,
// which is problematic when that number
// is large or changes are necessary.
}
Is there a way to solve this problem or do I have to essentially rewrite the same code for all classes that extend A?
You can, but it requires you to do quite a lot of the work
you are asking to avoid:
class A<T extends A<T>> {
final T Function(int, int) _constructor;
final int x;
final int y;
A._(this._constructor, this.x, this.y);
T copy({int? x, int? y}) => _constructor(x ?? this.x, y ?? this.y);
}
class B extends A<B> {
B(int x, int y) : super._((int x, int y) => B(x, y), x, y);
}
(The code will get shorter when Dart gets constructor tear-offs, then it's just, super._(B, x, y);.)
You cannot, currently, inherit constructors, and you can't create an instance of a type that you don't know yet (because constructors are not inherited, so you don't know if the constructor exists). The only way to abstract over actual behavior (which code to run) is to capture it in a closure and pass it as a function.

defining a generic class with parametrized type that expects more than one abstract class implementation in dart

interfaces
abstract class Adder<T> {
T add(T a, T b);
}
abstract class Multiplier<T> {
T multiply(T a, T b);
}
abstract class Displayer<T> {
void display(T a);
}
An implementation that just happens to implement all three.
class IntImpl implements Adder<int>, Multiplier<int>, Displayer<int> {
#override
int add(int a, int b) {
return a + b;
}
#override
int multiply(int a, int b) {
return a * b;
}
#override
void display(int a) {
print('printing: ${a}');
}
}
A consumer that needs support for two of the interfaces.
But, I could not find how to declare such a thing.
class DisplayingAdder<T, K extends Adder<T>> {
final K engine;
DisplayingAdder(this.engine);
T addAndDisplay(T a, T b) {
final r = engine.add(a, b);
// How do I change DisplayingAdder class parametrization to make the next line functional?
// engine.display(r);
return r;
}
}
Code to exercise the above
void main() {
final e1 = IntImpl();
final da = DisplayingAdder(e1);
da.addAndDisplay(3,4);
}
Not sure what can be changed to allow the generic parameter to declare support for more than one abstract class.
You can't restrict a generic type to a type that implements multiple supertypes. The best you're going to have to do is separate engine into an object that implements Adder and an object that implements Displayer, then pass the instance of IntImpl to both. (This is more scalable anyway since it also allows you to pass different values to each if you wanted.)
class DisplayingAdder<T, A extends Adder<T>, D extends Displayer<T>> {
final A adder;
final D displayer;
DisplayingAdder(this.adder, this.displayer);
T addAndDisplay(T a, T b) {
final r = adder.add(a, b);
displayer.display(r);
return r;
}
}
void main() {
final e1 = IntImpl();
final da = DisplayingAdder(e1, e1);
da.addAndDisplay(3,4);
}

How does one obtain data that has been returned from a method? (Java)

This might be a really stupid question but what happens to data that is returned from a method? For example, if I have a method that adds two numbers and I tell it to return the sum, how would I access that information from the place where the method was called?
Assuming your question is related with java.
You could assign the whole method to a new variable.
public class Test {
public static void main(String args[]){
int value1=2;
int value2=5;
int sum=sum(value1,value2);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
return value1+value2;
}
}
What is actually happening, is that the method signature sum(value1,value2) holds the result of the 2 numbers summation. There is also another way of writing the code inside the method but the result will be the same.
For example:
public class Test {
public static void main(String args[]){
int sum=sum(2,5);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
int sum=value1+value2;
return sum;
}
}
P.S. You could try to use the above samples directly. They will compile and run.
In most languages, you access the result of a function by putting the function call on the right hand side of an assignment expression.
For example, in Python, you can assign the result of calling the built-in len function on a list to a variable called x by doing the following:
x = len([1, 2, 3])

Method to create and store method chain at runtime

The problem I have is that I need to do about 40+ conversions to convert loosely typed info into strongly typed info stored in db, xml file, etc.
I'm plan to tag each type with a tuple i.e. a transformational form like this:
host.name.string:host.dotquad.string
which will offer a conversion from the input to an output form. For example, the name stored in the host field of type string, the input is converted into a dotquad notation of type string and stored back into host field. More complex conversions may need several steps, with each step being accomplished by a method call, hence method chaining.
Examining further the example above, the tuple 'host.name.string' with the field host of name www.domain.com. A DNS lookup is done to covert domain name to IP address. Another method is applied to change the type returned by the DNS lookup into the internal type of dotquad of type string. For this transformation, there is 4 seperate methods called to convert from one tuple into another. Some other conversions may require more steps.
Ideally I would like an small example of how method chains are constructed at runtime. Development time method chaining is relatively trivial, but would require pages and pages of code to cover all possibilites, with 40+ conversions.
One way I thought of doing is, is parsing the tuples at startup, and writing the chains out to an assembly, compiling it, then using reflection to load/access. Its would be really ugly and negate the performance increases i'm hoping to gain.
I'm using Mono, so no C# 4.0
Any help would be appreciated.
Bob.
Here is a quick and dirty solution using LINQ Expressions. You have indicated that you want C# 2.0, this is 3.5, but it does run on Mono 2.6. The method chaining is a bit hacky as i didn't exactly know how your version works, so you might need to tweak the expression code to suit.
The real magic really happens in the Chainer class, which takes a collection of strings, which represent the MethodChain subclass. Take a collection like this:
{
"string",
"string",
"int"
}
This will generate a chain like this:
new StringChain(new StringChain(new IntChain()));
Chainer.CreateChain will return a lambda that calls MethodChain.Execute(). Because Chainer.CreateChain uses a bit of reflection, it's slow, but it only needs to run once for each expression chain. The execution of the lambda is nearly as fast as calling actual code.
Hope you can fit this into your architecture.
public abstract class MethodChain {
private MethodChain[] m_methods;
private object m_Result;
public MethodChain(params MethodChain[] methods) {
m_methods = methods;
}
public MethodChain Execute(object expression) {
if(m_methods != null) {
foreach(var method in m_methods) {
expression = method.Execute(expression).GetResult<object>();
}
}
m_Result = ExecuteInternal(expression);
return this;
}
protected abstract object ExecuteInternal(object expression);
public T GetResult<T>() {
return (T)m_Result;
}
}
public class IntChain : MethodChain {
public IntChain(params MethodChain[] methods)
: base(methods) {
}
protected override object ExecuteInternal(object expression) {
return int.Parse(expression as string);
}
}
public class StringChain : MethodChain {
public StringChain(params MethodChain[] methods):base(methods) {
}
protected override object ExecuteInternal(object expression) {
return (expression as string).Trim();
}
}
public class Chainer {
/// <summary>
/// methods are executed from back to front, so methods[1] will call method[0].Execute before executing itself
/// </summary>
/// <param name="methods"></param>
/// <returns></returns>
public Func<object, MethodChain> CreateChain(IEnumerable<string> methods) {
Expression expr = null;
foreach(var methodName in methods.Reverse()) {
ConstructorInfo cInfo= null;
switch(methodName.ToLower()) {
case "string":
cInfo = typeof(StringChain).GetConstructor(new []{typeof(MethodChain[])});
break;
case "int":
cInfo = typeof(IntChain).GetConstructor(new[] { typeof(MethodChain[]) });
break;
}
if(cInfo == null)
continue;
if(expr != null)
expr = Expression.New(cInfo, Expression.NewArrayInit( typeof(MethodChain), Expression.Convert(expr, typeof(MethodChain))));
else
expr = Expression.New(cInfo, Expression.Constant(null, typeof(MethodChain[])));
}
var objParam = Expression.Parameter(typeof(object));
var methodExpr = Expression.Call(expr, typeof(MethodChain).GetMethod("Execute"), objParam);
Func<object, MethodChain> lambda = Expression.Lambda<Func<object, MethodChain>>(methodExpr, objParam).Compile();
return lambda;
}
[TestMethod]
public void ExprTest() {
Chainer chainer = new Chainer();
var lambda = chainer.CreateChain(new[] { "int", "string" });
var result = lambda(" 34 ").GetResult<int>();
Assert.AreEqual(34, result);
}
}
The command pattern would fit here. What you could do is queue up commands as you need different operations performed on the different data types. Those messages could then all be processed and call the appropriate methods when you're ready later on.
This pattern can be implemented in .NET 2.0.
Do you really need to do this at execution time? Can't you create the combination of operations using code generation?
Let me elaborate:
Assuming you have a class called Conversions which contains all the 40+ convertions you mentioned like this:
//just pseudo code..
class conversions{
string host_name(string input){}
string host_dotquad(string input){}
int type_convert(string input){}
float type_convert(string input){}
float increment_float(float input){}
}
Write a simple console app or something similar which uses reflection to generate code for methods like this:
execute_host_name(string input, Queue<string> conversionQueue)
{
string ouput = conversions.host_name(input);
if(conversionQueue.Count == 0)
return output;
switch(conversionQueue.dequeue())
{
// generate case statements only for methods that take in
// a string as parameter because the host_name method returns a string.
case "host.dotquad": return execute_host_dotquad(output,conversionQueue);
case "type.convert": return execute_type_convert(output, conversionQueue);
default: // exception...
}
}
Wrap all this in a Nice little execute method like this:
object execute(string input, string [] conversions)
{
Queue<string> conversionQueue = //create the queue..
case(conversionQueue.dequeue())
{
case "host.name": return execute_host_name(output,conversionQueue);
case "host.dotquad": return execute_host_dotquad(output,conversionQueue);
case "type.convert": return execute_type_convert(output, conversionQueue);
default: // exception...
}
}
This code generation application need to be executed only when your method signatures changes or when you decide to add new transformations.
Main advantages:
No runtime overhead
Easy to add/delete/change the conversions (code generator will take care of the code changes :) )
What do you think?
I apologize for the long code dump and the fact that it is in Java, rather than C#, but I found your problem quite interesting and I do not have much C# experience. Hopefully you will be able to adapt this solution without difficulty.
One approach to solving your problem is to create a cost for each conversion -- usually this is related to the accuracy of the conversion -- and then perform a search to find the best possible conversion sequence to get from one type to another.
The reason for needing a cost function is to choose among multiple conversion paths. For example, converting from an integer to a string is lossless, but there is no guarantee that every string can be represented by an integer. So, if you had two conversion chains
string -> integer -> float -> decimal
string -> float -> decimal
You would want to select the second one because it will reduce the chance of a conversion failure.
The Java code below implements such a scheme and performs a best-first search to find an optimal conversion sequence. I hope you find it useful. Running the code produces the following output:
> No conversion possible from string to integer
> The optimal conversion sequence from string to host.dotquad.string is:
> string to host.name.string, cost = -1.609438
> host.name.string to host.dns, cost = -1.609438 *PERFECT*
> host.dns to host.dotquad, cost = -1.832581
> host.dotquad to host.dotquad.string, cost = -1.832581 *PERFECT*
Here is the Java code.
/**
* Use best-first search to find an optimal sequence of operations for
* performing a type conversion with maximum fidelity.
*/
import java.util.*;
public class TypeConversion {
/**
* Define a type-conversion interface. It converts between to
* user-defined types and provides a measure of fidelity (accuracy)
* of the conversion.
*/
interface ITypeConverter<T, F> {
public T convert(F from);
public double fidelity();
// Could use reflection instead of handling this explicitly
public String getSourceType();
public String getTargetType();
}
/**
* Create a set of user-defined types.
*/
class HostName {
public String hostName;
public HostName(String hostName) {
this.hostName = hostName;
}
}
class DnsLookup {
public String ipAddress;
public DnsLookup(HostName hostName) {
this.ipAddress = doDNSLookup(hostName);
}
private String doDNSLookup(HostName hostName) {
return "127.0.0.1";
}
}
class DottedQuad {
public int[] quad = new int[4];
public DottedQuad(DnsLookup lookup) {
String[] split = lookup.ipAddress.split(".");
for ( int i = 0; i < 4; i++ )
quad[i] = Integer.parseInt( split[i] );
}
}
/**
* Define a set of conversion operations between the types. We only
* implement a minimal number for brevity, but this could be expanded.
*
* We start by creating some broad classes to differentiate among
* perfect, good and bad conversions.
*/
abstract class PerfectTypeConversion<T, F> implements ITypeConverter<T, F> {
public abstract T convert(F from);
public double fidelity() { return 1.0; }
}
abstract class GoodTypeConversion<T, F> implements ITypeConverter<T, F> {
public abstract T convert(F from);
public double fidelity() { return 0.8; }
}
abstract class BadTypeConversion<T, F> implements ITypeConverter<T, F> {
public abstract T convert(F from);
public double fidelity() { return 0.2; }
}
/**
* Concrete classes that do the actual conversions.
*/
class StringToHostName extends BadTypeConversion<HostName, String> {
public HostName convert(String from) { return new HostName(from); }
public String getSourceType() { return "string"; }
public String getTargetType() { return "host.name.string"; }
}
class HostNameToDnsLookup extends PerfectTypeConversion<DnsLookup, HostName> {
public DnsLookup convert(HostName from) { return new DnsLookup(from); }
public String getSourceType() { return "host.name.string"; }
public String getTargetType() { return "host.dns"; }
}
class DnsLookupToDottedQuad extends GoodTypeConversion<DottedQuad, DnsLookup> {
public DottedQuad convert(DnsLookup from) { return new DottedQuad(from); }
public String getSourceType() { return "host.dns"; }
public String getTargetType() { return "host.dotquad"; }
}
class DottedQuadToString extends PerfectTypeConversion<String, DottedQuad> {
public String convert(DottedQuad f) {
return f.quad[0] + "." + f.quad[1] + "." + f.quad[2] + "." + f.quad[3];
}
public String getSourceType() { return "host.dotquad"; }
public String getTargetType() { return "host.dotquad.string"; }
}
/**
* To find the best conversion sequence, we need to instantiate
* a list of converters.
*/
ITypeConverter<?,?> converters[] =
{
new StringToHostName(),
new HostNameToDnsLookup(),
new DnsLookupToDottedQuad(),
new DottedQuadToString()
};
Map<String, List<ITypeConverter<?,?>>> fromMap =
new HashMap<String, List<ITypeConverter<?,?>>>();
public void buildConversionMap()
{
for ( ITypeConverter<?,?> converter : converters )
{
String type = converter.getSourceType();
if ( !fromMap.containsKey( type )) {
fromMap.put( type, new ArrayList<ITypeConverter<?,?>>());
}
fromMap.get(type).add(converter);
}
}
public class Tuple implements Comparable<Tuple>
{
public String type;
public double cost;
public Tuple parent;
public Tuple(String type, double cost, Tuple parent) {
this.type = type;
this.cost = cost;
this.parent = parent;
}
public int compareTo(Tuple o) {
return Double.compare( cost, o.cost );
}
}
public Tuple findOptimalConversionSequence(String from, String target)
{
PriorityQueue<Tuple> queue = new PriorityQueue<Tuple>();
// Add a dummy start node to the queue
queue.add( new Tuple( from, 0.0, null ));
// Perform the search
while ( !queue.isEmpty() )
{
// Pop the most promising candidate from the list
Tuple tuple = queue.remove();
// If the type matches the target type, return
if ( tuple.type == target )
return tuple;
// If we have reached a dead-end, backtrack
if ( !fromMap.containsKey( tuple.type ))
continue;
// Otherwise get all of the possible conversions to
// perform next and add their costs
for ( ITypeConverter<?,?> converter : fromMap.get( tuple.type ))
{
String type = converter.getTargetType();
double cost = tuple.cost + Math.log( converter.fidelity() );
queue.add( new Tuple( type, cost, tuple ));
}
}
// No solution
return null;
}
public static void convert(String from, String target)
{
TypeConversion tc = new TypeConversion();
// Build a conversion lookup table
tc.buildConversionMap();
// Find the tail of the optimal conversion chain.
Tuple tail = tc.findOptimalConversionSequence( from, target );
if ( tail == null ) {
System.out.println( "No conversion possible from " + from + " to " + target );
return;
}
// Reconstruct the conversion path (skip dummy node)
List<Tuple> solution = new ArrayList<Tuple>();
for ( ; tail.parent != null ; tail = tail.parent )
solution.add( tail );
Collections.reverse( solution );
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb);
sb.append( "The optimal conversion sequence from " + from + " to " + target + " is:\n" );
for ( Tuple tuple : solution ) {
formatter.format( "%20s to %20s, cost = %f", tuple.parent.type, tuple.type, tuple.cost );
if ( tuple.cost == tuple.parent.cost )
sb.append( " *PERFECT*");
sb.append( "\n" );
}
System.out.println( sb.toString() );
}
public static void main(String[] args)
{
// Run two tests
convert( "string", "integer" );
convert( "string", "host.dotquad.string" );
}
}

Resources