Well, you can get part of the way there, by using a class associated type
class HasOpen a where
type Open a :: *
open :: a -> Open a
This lets you use type inference in one direction, without requiring that every result be a member of a data family. On the other hand, type inference just became directional, like in C#. you can't use the type of Open a to infer the type a because you've lost injectivity.
You'd need a data type family to guarantee injectivity and determine a from the context of Open a, and that yields an ugly mess. Since each container would have to yield a distinct value type and interoperability goes out the window.
On the other hand, the mixture of fixed type slots and type family slots gets you a pretty good compromise. You typically know the type of the structs whose members you are asking for.
-Edward Kmett
The usual suggestion I see for this sort of thing is to create a
typeclass for the operations you care about[1][2]. For example:
-------------------------------------------------------------------------------------------
class HasOpen a where
open :: a -> Handle
data DB
data FS
openDB :: DB -> Handle
openFS :: FS -> Handle
instance DB HasOpen where open = openDB
instance FS HasOpen where open = openFS
-------------------------------------------------------------------------------------------
Of course, this doesn't allow you to have functions share the same
name if they have different signatures, as in your (open :: FS ->
File) example. To be honest, I think the C / Haskell approach of
unambiguously-identified functions is clearly superior to the C++ / C#
/ Java "class as namespace" idiom, which has caused me no end of
grief.
Dynamic languages such as Python and Ruby, of course, can return
anything from anywhere. This is nice in some cases, but having used
both extensively I think (static typing+inference) is a better
solution than dynamic typing.
Type inference and static typing are separate; inference makes static
> Now, in Haskell we have type inference, which is "The Good Thing" as
> it allows to "validate" your program at compile time. Hence, the idea
> coming up to my mind is that type inference actually forbids a
> type-directed resolution of names as in C++ or Java.
>
> Is this correct?
typing usable, but static typing makes compile-type correctness
verification easier. And it's not inference making your goal
impossible, but the fact that Haskell (like C) does not support
arbitrary overloading.
[1] http://www.mail-archive.com/haskell-cafe@haskell.org/msg64844.html
[2] http://stackoverflow.com/questions/1897306/haskell-record-syntax-and-type-classes
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe