hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

OOP in F# is annoying

Last post 07-04-2010, 14:24 by Sebastian.Ferreyra. 23 replies.
Page 1 of 2 (24 items)   1 2 Next >
Sort Posts: Previous Next
  •  10-31-2008, 10:48 7579

    OOP in F# is annoying

    Hello,

    I've wanted to write simple application in F# and I've encountered one significant flaw in F#.

    In the code
    type IOne =
    abstract AddTwo : int -> int

    type One() =
    interface IOne with
    member o.AddTwo (i) = i + 2

    When I want to use method AddTwo() I need to cast the object of class One to interface IOne:
    let simpleAdd = new One()
    let test = (simpleAdd :> IOne).AddTwo(2)

    For me this use of method defined in the interface implemented by the class is unacceptable.
    Basically because the code that uses class One needs to be aware what interfaces the class implement, and what methods belong to that interface, this just brakes encapsulation.

    tomasp in the post http://cs.hubfs.net/forums/permalink/3709/3709/ShowThread.aspx#3709 proposed to create additional methods in the class, however this approach brakes rule "Don't repeat yourself".

    That is way I'd like to know if this problem will be solved?
    When I think about using interfaces and inheritance the way it is now, it makes me start thinking of writing the code in C#.

    It is normal in application to have many classes and interfaces, and I just can't imagine myself writing such an annoying additional code.
  •  10-31-2008, 11:16 7580 in reply to 7579

    Re: OOP in F# is annoying

    Hi,
    I agree that this is a limitation, but I encounter it only very rarely when writing code in F#. I think it is because if you're writing code in F# (even when using object types and interfaces), you don't need as many classes as in C#, because there is often easier way to solve the problem. If you're required to write very object-oriented code (for example because it is a library used by C# client) then it is probably easier to use C# - but you can still write some core parts in F#.

    Anwyay, in the case you mentioned, you can use obejct expressions and achieve the same thing more elegantly:

    type IOne =
        abstract AddTwo : int -> int
    let simpleAdd =
      { new IOne with
          member x.AddTwo(i) = i + 2 }
    let test = simpleAdd.AddTwo(2)

    I think it is important to keep in mind that the design of F# programs is a bit different then when writing C# programs, but if you find the right way then it becomes very elegant & easy to write. If you want to post some more real-world example of what you're doing then we may give you some better hints!

    Hope this helps!
    Tomas


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  10-31-2008, 11:44 7581 in reply to 7580

    Re: OOP in F# is annoying

    Thanks, however I just want to get elegant code in general.

    If you had just one interface and let's say five classes implemnting it, the code would look like jungle. You would have two options:
    1) making your code awful by adding additional methods. How to name them?
    2) forcing people using your code to cast every object ;) so annoying, and I am not a fan of casting.

    I mean that the way the OOP part of F# is now made, brakes many good programming practices. There is no good way to walk around this problem.

    Do you know if they are going to address this problem in next release?
  •  10-31-2008, 12:00 7582 in reply to 7581

    Re: OOP in F# is annoying

    Hi,
    I think the key point is that in F# you don't usually have classes that implement an interface (that would be used directly by the user of the class) and add lot of new functionality by having additional members.

    When you just want to implement an interface then object expressions are often the best option. However you can use classes too - and you don't need casting if you just want to call a method/function that takes the interface as an argument:


    type IFoo =
      abstract Foo : unit -> unit
    let callFoo(f:IFoo) = f.Foo()
    type Foo1() =
      interface IFoo with
        override x.Foo() = printfn "Foo1"
    type Foo2() =
      member x.Other() = printfn "Other"
      interface IFoo with
        override x.Foo() = printfn "Foo2"
    let f1 = new Foo1()
    let f2 = new Foo2()
    // Call function that works with the interface
    callFoo f1
    callFoo f2
    // we can still use other members
    f2.Other()

    So, I think that F# just forces you to separate parts of the code that works with interfaces implemented by the class and parts that use additional members.


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  10-31-2008, 12:09 7583 in reply to 7581

    Re: OOP in F# is annoying

    Regarding option 1 and 'how to name', use the exact same name and signature.  Then you'll have a class that's much like what you get in C#, the only difference being you have to define both the interface method and the class method (whose implementation just delegates to the interface), whereas in C# you just define the class method (and it automatically fills the interface slot as well).

    We'll consider this suggestion for the next release.  But I echo Tomas' comment that this doesn't occur too often in practice, especially when programming with 'F# style'.

  •  10-31-2008, 12:40 7584 in reply to 7583

    Re: OOP in F# is annoying

    tomasp, I think that using additional function to use a part of class's methods is just wrong, and would be hard to understand for someone who has no idea about F#.

    brianmcn, You convinced me to stick with option 1), I still thinks that every redundancy is bad, and just asks for mistakes.
    Can You summarize why F# doesn't have interfaces and inheritance known in C#?

    Btw, I've read "Expert F#", Could You recommend where I can read about good practices in F#?
  •  10-31-2008, 14:49 7586 in reply to 7584

    Re: OOP in F# is annoying

    C# has explicit interfaces too:

        public interface IFoo
        {
            void Method();
        }
        public class Foo : IFoo
        {
            void IFoo.Method()
            {
            }
            public static void Example()
            {
                Foo foo = new Foo();
                foo.Method();  // does not compile
                (foo as IFoo).Method(); // does
            }
        }

    The differences are that in F#, interfaces are implemented explicitly by default, whereas in C# they are not, and that in F# there is no syntax to have one method implement both.

    The value of explicit interfaces is that they can help reduce complexity and make code more explicit.  With many interfaces, you would never call the method on a concrete object, you would only call it on an object that was already upcast to the type.  That is, often you'll have a class implement an interface, not so that a user will new up the class and call the method, but instead because a user will new up the class and hand it to some framework that knows how to process IFoos or whatever.  In that case, the framework will just keep a collection of IFoo objects and call those methods.  When a user does "myFoo." and the intellisense comes up, if IFoo is implemented explicitly, the IFoo methods don't appear, reducing the user-facing complexity for common user scenarios.  (Try newing up some WPF objects and look at the hundreds and hundreds of methods that appear in intellisense.  How many of those are you likely to call?  How many of those are only there to support interaction with other parts of WPF framework?  Wouldn't it be nice if more of those interfaces you don't care about were out of your face?)

    On the other hand, there are also cases where the interface methods are also intentionally user-facing.  List : IList is a good example.  Users who have just newed up a List will call Add(), Clear(), etc.  But also general methods that work on arbitrary-concrete-collection ILists will also call these methods.  In this case, you don't want the interface to be explicit, you want both the users of the concrete type and users targeting the interface to see the same method.

    C# prefers the latter strategy, but has a little-known and little-used syntax support for the former.  F# prefers the former strategy, and has no syntax sugar for the latter (which is why you have to 'repeat yourself').

    I don't know what 'the right/best answer is', but I hope this illuminates the issues that play into the pros and cons of have interface methods automatically show up on concrete class types.

  •  11-20-2008, 21:42 7887 in reply to 7583

    Re: OOP in F# is annoying

    I agree that this is less of an issue when you program in a functional style.

    IMO, the practical issue here is more about interoperability with C#.  Right now I am starting to write new code in my legacy C# code base in F#.  One way I have started swaping out some of the old C# code with f# is to impliment interfaces from some of the C# code. 

    It is probably a good idea to make this transition process (and interoperability in general) as smooth as possible
  •  01-13-2009, 13:41 8555 in reply to 7887

    Re: OOP in F# is annoying

    Coming from Java & C#, I find having to cast up to the interface type in this situation to be a bit strange and verbose.  May be I'll get used to it.  Is it possible to eliminate the need to do the upcast?  Or is this truly a better design?

    type IMathService =
      abstract Multiply : int * int -> int
     
    type MathService() =
      interface IMathService with
        member x.Multiply(a:int, b:int) = a * b
       
    let math = new MathService() :> IMathService
    let result = math.Multiply(5,4)

    See F# Manual, 8.5 Interface Specifications and Implementations
    "Interface members are called by first casting to the interface type:"
    http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec2.aspx#_Toc207785703

  •  01-13-2009, 14:21 8556 in reply to 8555

    Re: OOP in F# is annoying

    You need the upcast.  I think the other messages on this thread describe this well in detail.
  •  01-13-2009, 16:43 8562 in reply to 8556

    Re: OOP in F# is annoying

    Yes, I realize that that the upcast is required in the current design/implementation of F#.  I'm curious if there has been any thought to removing the need for an upcast in the design of the F# language.  I do not know if that would be a good design decision or not.
  •  01-13-2009, 16:51 8563 in reply to 8562

    Re: OOP in F# is annoying

    In two of my previous posts I said

    We'll consider this suggestion for the next release.

    and

    I don't know what 'the right/best answer is', but I hope this illuminates the issues that play into the pros and cons of have interface methods automatically show up on concrete class types.

    So yes, we will think about it; there are pros and cons and it's not necessarily totally clear to us if it's 'good' or not either.

  •  01-15-2009, 0:10 8578 in reply to 7579

    Re: OOP in F# is annoying

    saner:

    When I want to use method AddTwo() I need to cast the object of class One to interface IOne:
    let simpleAdd = new One()
    let test = (simpleAdd :> IOne).AddTwo(2)

    For me this use of method defined in the interface implemented by the class is unacceptable.
    Basically because the code that uses class One needs to be aware what interfaces the class implement, and what methods belong to that interface, this just brakes encapsulation.


    The problem is that you're actually confusing things. F# enforces encapsulation by making you aware of your interfaces.
    What it's trying to tell you is that if you want to do operations on "IOne" types then you should be a bit more explicit about it.

    This is one of the cases where type annotations come in handy like this:

    [code]
    #light

    type IOne = abstract AddTwo : int -> int

    type One() =
    interface IOne with
    member this.AddTwo i = i + 2

    let addTwo (t:IOne) = t.AddTwo
    let test = addTwo (new One())

    print_any (test 2)
    [/code]

    As you can see the "test" method can seamlessly pass a One as a IOne. And this is should be the common case that who ever is doing an operation know what protocol/interface to follow and you encode that with types when needed.

    This is no different than in C# following the rule to use the least specific interface/class possible to get the job done.
    It promotes encapsulation by making you think about what is really needed to accomplish a task in essence driving complexity down.
  •  01-15-2009, 0:19 8579 in reply to 7586

    Re: OOP in F# is annoying

    Can I plead to the designers and caretakers of F# to keep this the way it is?

    Please! For the love of all things simple and clean.

    Yes comming from a C++ and C# background I stumbled and fell on this issue, I even started argumenting that it was broken flawed and a complete and utter disgrace.

    But I was wrong. Dead wrong. The thing is that the F# behaviour promotes among other things IoC and makes it clear what my dependencies really are. It helps keep methods small and focused.

    In the example of using a List as an IList to Add/Clear/DoStuff not having the implicit usage actually helps separate the creating of a concrete class from the abstract filling. And that's a good thing.

    It helps us bring forth the structure and beauty of interface segregation and helps us think about what the minimal interface needed for an operation really is.
  •  01-15-2009, 11:36 8588 in reply to 8579

    Re: OOP in F# is annoying

    I agree with torbjorn.gyllebring 110%!
    Paulmichael Blasucci
Page 1 of 2 (24 items)   1 2 Next >
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems