• 0

C# equivalent base(...) in F# and other Qs


Question

This is what I have, issue is it creates two copies of width / height / data

 

[<AbstractClass>]
type IImage<'T when 'T : struct> (width, height, data : 'T[]) =

    let mutable width = width
    let mutable height = height
    let mutable data = data

type Image public (width, height, data : double[]) =

    inherit IImage<double>(width, height, data)
This is what I want (C#) and actually thought I was doing

 

    public abstract class IImage<T>
        where T : struct
    {
        public IImage(int width, int height, T[] data)
        {
            if (data.Length != width * height)
            {
                throw new ArgumentException();
            }

            this._width = width;
            this._height = height;
            this._data = data;
        }
    }

    public class Image : IImage<double>
    {

        public Image(int width, int height, double[] data)
            : base(width, height, data)
        {
        }
    }
width, height, data need to be protected in C# speak

I tried inherit without arguments with a new() = {..} but that does not want to compile

Also I am not sure who what this is called and how this is done in F# (I implemented it as this.At with get() currently)

 

public T this[int i, int j]
Also one horrible moronic limitation of C# is the inability to have a generic which supports + - / * (double, float, int32, uint32, int64, decimal, etc)

which forces a lot of functions to be abstract, or cast to dynamic

but when I constrain 'T a bit

'T when 'T : struct and 'T : (static member (+) : 'T -> 'T)
this (rewritten from C# private IImage<T> _map(Func<int, T> _func, bool _parallel))

    member this.baseMap ((func: int -> 'T), (concurrent : Option<bool>)) =
        if istrue concurrent then
            Parallel.For (0, data.Length, (fun i -> data.[i] <- func i))
            |> ignore
        else
            for i in 0 .. data.Length - 1 do 
            data.[i] <- (func i)
gives,

 

This code is not sufficiently generic. The type variable  ^T when  ^T : struct and  ^T : (static member ( + ) :  ^T ->  ^T)
Which makes no sense to me.
Link to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 0
Also I am not sure who what this is called and how this is done in F# (I implemented it as this.At with get() currently)

public T this[int i, int j]

What you're looking for is called Indexed Properties.

 

As for your inheritance problem, I think what you should be doing is:

[<AbstractClass>]
type IImage<'T when 'T : struct> =
    new (w, h, d) = { width = w; height = h; data = d}
    val mutable width : int
    val mutable height : int
    val mutable data : 'T[]

type Image =
    inherit IImage<double>
    new (width, height, data) = { inherit IImage<double>(width, height, data) }

(There might be an even better way to write this, I'm not too fluent in F# yet). It seems like questionable design, though, to have a type that represents a value have mutable fields. Why wouldn't you make the fields immutable? You could then simply write:

[<AbstractClass>]
type IImage<'T when 'T : struct>(w:int, h:int, d:'T[]) =
    member x.Width = w
    member x.Height = h
    member x.Data = d

type Image(w, h, d) =
    inherit IImage<double>(w, h, d)

Also it's not clear to me what you're trying to achieve with this class hierarchy. More common in F# for defining operations on several types is to use pattern matching.

Link to comment
Share on other sites

  • 0

Ok I think I solved the first question,

I got rid of arguments in constructor in the Abstract Class,

[<AbstractClass>]
type IImage<'T when 'T : struct> () =

    class

    [<DefaultValue>]
    val mutable width : int
    [<DefaultValue>]
    val mutable height : int
    [<DefaultValue>]
    val mutable data : 'T[]
and

type Image() =

    inherit IImage<double>()

    new (width, height, data) as this =
        new Image() then
        this.height <- height
        this.width <- width
        this.data <- data
did the trick

Currently thinking about how to double -> Complex with a few lines of code as possible as in C# it is implicit

And if anyone is wandering, this is what I do instead of talking to people

Link to comment
Share on other sites

  • 0

I have to vent a bit, F# is a horrible language.

Reasons,

1. Compiler warnings on StructLayout Explicit / FieldOffset

2. Can't multiply double and complex without converting double to complex explicitly.

3. Interface functions are hidden, you have to cast the implementing class to the interface whenever you want to access the functions from the interface.

4. You have to cast down to the interface if your functions take in the interface

5. Folders not allowed in solution (at least not in Visual Studio 2012 Pro)

6. Order of files in your solution influences compilation

7. Lack of implicit interface, implicit casting, folders, and order based compilation makes this language unsuitable for anything remotely complex.

8. To add to #7 - no regions.

9. To add even more - overloads are not allowed.

10. There is an F# extension method syntax and, a completely different way to get said extension method to work in C#

11. = means two separate things

12. No circular dependencies

Rest is fine - rest of the language is great, but really I can't use this language until the above issues go away.

Might try VB.NET ...

Edited by _Alexander
Link to comment
Share on other sites

  • 0

No circular dependencies is a huge strong point of F#. It forces you to fix your design. A circular dependency between components means that they're not really composable independently but must be taken as a whole, as a super-component. If your whole project is tangled with circular dependencies, this means you can't easily extract anything reusable from it. Everything depends on everything. I strongly suggest you read this series of articles on the topic.

 

No implicit casting is another great feature that promotes obviously correct code that doesn't hide any corner cases or side-effects. The added verbosity is dwarfed by the overall terseness of the language compared to C# which is drowned in redundant type specifiers, braces and other syntactic noise.

 

Function overloading - you can overload class methods, and inline methods with static generic types ("^") provides a very powerful mechanism for defining operations on unrelated types which is completely absent in other .NET languages. See http://stackoverflow.com/questions/501069/functions-with-generic-parameter-types

 

Lack of implicit interface implementation simply means that F# is a bit verbose around OOP, because it tries to be a great functional language first and an OOP language second, whereas C# tries to be a great OOP language first and added functional bits as an afterthought. If you try to do functional programming in C#, the syntax gets horrible very quickly, much more so than OOP in F#. I think you're focusing too much on minor syntactic details and are not taking advantage of the functional paradigm that feels most natural in F#.

 

No regions is perhaps a matter of opinion, but I hate them with a passion and have installed the I Hate #Regions extensions at work because our coding guidelines dictate that every bit of code is inside several levels of useless #regions and this makes what would be a 1-line class in F# 30-lines long in C#.

 

Compiler warnings on StructLayout - could you elaborate?

 

Anyway, F# is way better than C#, especially for large projects: you get no null pointers which is basically 50% of your bugs fixed for free; you get immutability by default everywhere; you cut your codebase size by a factor of 4 or more; you get statically defined generics that allow you to make generic numerical code and other optimization tricks that are entirely impossible in C#; you're nudged into doing things in a stateless rather than stateful manner; proper support for algebraic types, fully enforced by the type system; you're forced to make your design actually hierarchical and modular which makes it inherently much easier to understand and maintain; and you still keep the ability to write unsafe mutable pointer arithmetic and what have you and full compatibility with .NET, and I could go on.

Link to comment
Share on other sites

  • 0

I use interfaces as statements that class "Foo" implements all functions from interface "IFoo".

Explicit interfaces make my head hurt, as they imply that "Foo" can have multiple "void Bar()" functions defined.

One from IBar for example and one from IFoo.

The biggest problem with F# method of doing thing though, is that I can't pass data : Foo[] to a function that takes data: IFoo[]

which, to me, is the whole point of interfaces.

I had to effectively create a new array for the code to compile "[| for i in foos -> i :> IFoo |]"

I try to bind similar functionality and use as generic of parameters as possible which is why I cannot wait for "params IEnumerable<T>"

I mean, making the following

    [StructLayout(LayoutKind.Explicit)]
    public struct PixelColor
    {
        /// <summary>
        /// 32 bit BGRA
        /// </summary>
        [FieldOffset(0)]
        public UInt32 BGRA;

        [FieldOffset(0)]
        public byte Blue;

        [FieldOffset(1)]
        public byte Green;

        [FieldOffset(2)]
        public byte Red;

        [FieldOffset(3)]
        public byte Alpha;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool operator ==(PixelColor item1, PixelColor item2)
        {
            return item1.BGRA == item2.BGRA;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool operator !=(PixelColor item1, PixelColor item2)
        {
            return item1.BGRA != item2.BGRA;
        }

        public override bool Equals(Object obj)
        {
            if (obj == null || this.GetType() != obj.GetType())
                return false;

            return (this == (PixelColor)obj);
        }

        public override int GetHashCode()
        {
            return this.BGRA.GetHashCode();
        }
    }
in F# will elicit a compiler warning. Even though F# lacks the mighty pointer, I wanted to see if I could Marshal things... gave up on that warning.

And yes, now that you mention it, optional parameters were wrapped in Option<T> which made them a headache... and I removed them.

Edited by _Alexander
Link to comment
Share on other sites

  • 0

F# supports pointers and all the C# unsafe features via the NativePtr module. I suppose the warning you're referring to is FS0009? Just disable it if you know what you're doing. It warns you that you're creating potentially unverifiable code because the fields may overlap (which they do in your case).

 

Note that AggressiveInlining is pointless for your equality operators as they are very short methods and will be inlined anyway. AggressiveInlining is useful when you have larger methods that may not be inlined due to their size.

 

The biggest problem with F# method of doing thing though, is that I can't pass data : Foo[] to a function that takes data: IFoo[]
which, to me, is the whole point of interfaces.

If the function only reads from the array, you can define the function as taking #IFoo[] and that should work (http://stackoverflow.com/a/7339601/154766). If the function must write to the array, then that would be unsafe; for instance the function could add FooBs to an array of FooAs (both implementing IFoo), and that's why F# doesn't let you do that easily.

 

Example:

 

type IFoo =
    interface
    end

type FooA() = interface IFoo
type FooB() = interface IFoo

let myMethod (arr:#IFoo[]) =
    arr |> Array.iter (printfn "%A") // Reading from the array is allowed
    // arr.[0] <- FooB() // But writing will cause the type of arr to be inferred as FooB[]

let arrFooA = [| FooA(); FooA();|]
myMethod (arrFooA)

 

As you can see, F# works very hard to not let you write code that could fail at run-time. :)

Link to comment
Share on other sites

This topic is now closed to further replies.