Giter VIP home page Giter VIP logo

Comments (4)

deech avatar deech commented on June 1, 2024

Sorry for the length of this response.

It's funny that you bring up WxHaskell's approach because that was the first avenue I explored mostly due to your reply [1] on haskell-cafe. It is indeed an elegant and simple but I ended up having to abandon it. The reason is suppose there is a class hierarchy in some OO language:

class Shape
   - int area
class Rectangle : Shape
   - int area (int, int)
class Square : Rectangle
   - int area (int)

Using the wxHaskell approach I can easily encode Rectangle's area but Square's implementation is impossible. I found a number of cases in the FLTK hierarchy where the type signature of a subclass function did not match the parent's.

Using the scheme in the current codebase you can call area <instance-of-Rectangle> 1 2, and area <instance-of-Square> 2, but area <instance-of-Rectangle> 1 will cause a compile time error asking for another argument. The error itself is quite readable. Note also that one does not have to qualify the area function call with Rectangle.area or Square.area, the correct implementation is determined solely by the type of the <instance-of-*> argument. Additionally this scheme is open, Rectangle could easily be split off into it's own package.

Having to raise the context stack is unfortunate. I do this because in working out which implementation of a function to dispatch a call to, the type system has to iterate down all the possible functions available to that "instance" and if there are over a certain number that can cause a context stack overflow.

I did have a type level function that used an type-level fixed-size buffer to keep the number of iterations lower, but could not get it below the default limit of 21, and it was not constant, and the code was ugly. Since I ended up having to raise the limit anyway so I figured the simpler less efficient implementation would be fine since the hit only happens at compile time and today's hardware can handle it. There is also talk among the GHC devs about raising the limit to something less ridiculous (like 1024).

Thanks for taking the time to write feedback!

[1] https://mail.haskell.org/pipermail/haskell-cafe/2013-September/110203.html

from fltkhs.

HeinrichApfelmus avatar HeinrichApfelmus commented on June 1, 2024

Ah, I see. Yeah, that would be one of the cases where the phantom type approach fails. But are you sure that this complexity is really needed? I mean, it is your call to make, but personally, I would be quite happy to use different names, say area and areaSquare for functions that have different numbers of arguments. In a way, you are implementing polymorphic records, and I am not entirely sure whether they are worth the complexity in this context. When writing a GUI, I would be more than happy to learn straightforward Haskell 98 type signatures, even if they differ from the C++ headers in some cases. After all, my focus would be on writing a GUI in Haskell, not so much on translating C++ code 1:1. Of course, that is just my personal taste, feel free to disregard it. 😄

from fltkhs.

deech avatar deech commented on June 1, 2024

That's a great point and I struggled with it. In fact if you look back in the commits I had the wxHaskell model almost fully implemented but had so many special functions like setItemMenuPrim, setItemBoxedMenu etc. that I aesthetically couldn't take it anymore. I barely wanted to use my own API. :)

As a way of penance for the complexity the Haddocks for all the widget modules show the functions with the type signatures the user would care about rather than the scary complex ones. It's not an amazing solution but it's the best I could come up with.

The context stack is the only piece of ugliness I couldn't totally hide from the end-user. Hopefully either GHC devs will increase the default stack size or someone cleverer than I will figure out how to keep the stack constant size and under 21.

Also this scheme relies heavily on phantom types and empty datatypes and is heavily inspired by wxHaskell, so I thank you for pointing me that way

from fltkhs.

HeinrichApfelmus avatar HeinrichApfelmus commented on June 1, 2024

Well, WxHaskell also has a couple of functions where this is an issue. The solution there was to make type classes for these cases. For instance, the Text class works for subclasses of both the MenuItem and Window classes, even though they have no common ancestor.

from fltkhs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.