Re: [Haskell-cafe] Just for a laugh...

2007-06-01 Thread rossberg
David Roundy wrote:
 On Fri, Jun 01, 2007 at 07:39:32PM +0100, Andrew Coppin wrote:

 No, I mean... how could you use unsafePerformIO to perform a typecast? I
 don't see a way to do that.

 Then I'm confused.  What typecast are you talking about?

cast :: a - b
cast x = unsafePerformIO (do writeIORef r x; readIORef r)
 where r = unsafePerformIO (newIORef undefined)

The problem is that the Hindley/Milner type inference algorithm is unsound
in the presence of effects - r may not be given polymorphic type. That's
exactly the reason for ML's dreaded value restriction.

- Andreas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Trouble with record syntax and classes

2007-02-27 Thread Andreas Rossberg

[EMAIL PROTECTED] wrote:


When you type class Foo in Java or C++, it does three things:

1. It declares a new type called Foo.

2. It declares a _set_ of types (i.e. a class).

3. It declares that the type Foo (and all of its subtypes) is a member
of the set of types Foo.


I would add:

4. Define a namespace, also called Foo, for a set of values (and 
probably nested classes).



In Haskell, these three operations are distinct.

1. You declare a new type using data or newtype.

2. You declare a new set of types using class.

3. You declare that a type is a member of a class using instance.


4. You define a new namespace using module.

Cheers,
- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Getting my feet wet - not in Haskell though

2006-12-24 Thread rossberg
Joachim Durchholz wrote:
 I'll move on to the alternatives - Alice ML and/or Clean. Both can
 serialize without forcing lazy subexpressions.

I don't know about Clean, but with respect to Alice ML this is not
correct: Alice ML uniformly blocks on futures upon pickling, including
lazy ones.

Sometimes you may want to pickle lazy suspensions as such, but more often
it is not what you want. In particular, the suspension can easily be
larger than its result, and the closure may contain resources which cannot
be pickled. If such a suspension was produced by an abstraction you may
even argue that making contained resources observable partially breaks the
abstraction. To adhere to uniformity, strong abstraction, and the
Principle of Least Surprise, we thus chose to force lazy futures in Alice
ML.

 No FUD, please ;-)

 And yes I know there are devils lurking in every language and
 environment. I'm pretty sure that Haskell has a few others to offer, too.
 (There's still no good introduction to Monads, for example. One that's
 understandable for a programmer who knows his Dijkstra well but no
 category theory. And a few other things.)

No FUD, please ;-) ;-)

Cheers,
- Andreas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Getting my feet wet - not in Haskell though

2006-12-24 Thread rossberg
Joachim Durchholz wrote:

 To adhere to uniformity, strong abstraction, and the Principle of
 Least Surprise, we thus chose to force lazy futures in Alice ML.

 Well, I wouldn't have expected that pickling has an effect (other than
 wrapping the value up for transfer), so at least I would have been
 greatly surprised.

That effect is just strictness. Since you generally cannot pickle a
future (and usually wouldn't want to), pickling naturally has to be
strict. Making lazy futures a special case, in this one single strict
operation, would be surprising (and extremely ad-hoc).

- Andreas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Aim Of Haskell

2006-12-12 Thread Andreas Rossberg

Claus Reinke wrote:


but on the Pascal note: is there anything in Pascal that Haskell doesn't
provide, and improves on (nested procedures, procedure parameters,
distinguishing in and out parameters, types, ..)?


Subrange types, maybe? But I'm sure Oleg will show us that Haskell 
already has them. :-)


- Andreas

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell] Num is such a fat and greedy class

2006-12-11 Thread Andreas Rossberg

Lennart Augustsson wrote:


let data Bar = ... in  ...


If you allow this you need to be very careful about type equality.  When 
is Bar equal to Bar?
If it's inside a recursive function, does each invocation get its own 
Bar?  (In SML the answer is yes.)


Can you give an example of how this would be observable in SML? AFAICS, 
there is no way to tell the difference, because generative type names 
are not allowed to escape their scope. (You can observe dynamic 
generativity of exception constructors, though.)


If you decide the answer is no, then 
is the beta rule still valid?


I think with the scoping restrictions in place the beta rule would not 
be affected.


- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Num is such a fat and greedy class

2006-12-11 Thread Andreas Rossberg

S.M.Kahrs wrote:

let data Bar = ... in  ...

If you allow this you need to be very careful about type equality.   
When is Bar equal to Bar?

If it's inside a recursive function, does each invocation get its
own Bar?  (In SML the answer is yes.) 


Not really.
In SML the answer used to be a clear no, that is: in the 1990
definition. However, that proved to be a matter of type-unsoundness,
and Claudio Russo came up with an example that used this feature to
break the type system. Having said this, this was based on the way the
type system was defined in the language definition, the problem did not
show up in implementations (which therefore failed to implement the
language standard :-).

The problem was fixed in the 1997 language standard.
But there the answer isn't yes either, it is more like: whatever it
is, you cannot tell, though technically it is still no.


Mh, technically, isn't it likewise neither? As you say, types are only 
generated statically, and are erased in the dynamic semantics, so how is 
it a no more than a yes?


As an aside (sorry if this is getting far too OT), in Alice ML we extend 
SML with dynamic types, and local types in fact *are* dynamically 
generative. This seemed to be the most natural semantics (and the only 
correct one in the presence of dynamic linking).



In the static semantics, a local datatype in SML is fresh.
However, this freshness is a static freshness, at compile time,
and every time the code is run the same type name (a uniqueness tag
for types) will be used: there is no run time type-checking, the type
name is generated once, at compile time.


Well, this is sort of true for types defined in functor bodies as well, 
still they are generative. The only semantical difference I see is that 
its local types are allowed to escape scope, and are (statically) 
renamed upon each application of the functor. No difference with respect 
to the dynamic semantics, however.



However, that type name is not allowed to leak to the outside, i.e.
not only is the identifier Bar not visible outside, the type of the
value returned by the let-expression must not contain the type name
associated with Bar. Thus, if a let-expression with a local datatype is
evaluated twice, it does not really matter whether it uses the same or a
different type name because encapsulation ensures
that these type names do not interfere with each other in any way.

In a nutshell: local types are not worth the trouble they cause.


I'm not quite sure how this follows from your explanation. :-) Don't you 
just need the same standard scoping restriction as for existential 
types? (Which they basically are, as we know.) Why do you consider it 
troublesome?


- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Re: GHC Error question

2006-12-06 Thread rossberg
[EMAIL PROTECTED] wrote:

 I'm afraid I may disagree about the quantification. Also, I'm cautious
 about the phrase ML and Haskell. In GHC 6.4, local type variables
 behave pretty much like those in ML (actually, GHC 6.2 was closer). In
 GHC 6.6, the behavior is completely different!

 Regarding the quantification: in ML (OCaml) we can write
   let foo (x:'a) y = (x+1,(y:'a))
 That does not mean that foo has the type forall 'a. 'a - 'a - ...
 Indeed, foo is not polymorphic and its inferred type is int - int -
 int * int. If there should be a quantifier in the above type, it
 probably should be 'exists' rather than 'forall'.  It seems in ML, the
 type variables are better understood as names of some types;

Be cautious about the phrase ML here as well. ;-) Because what you
describe only applies to OCaml. In Standard ML, the semantics of type
variables in annotations is saner: the equivalent of the above declaration
would be rejected. AFAICS it is basically equivalent to the new behaviour
of GHC 6.6.

Cheers,
- Andreas


___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell-cafe] Rank N type tutorial?

2006-10-27 Thread rossberg
Greg Buchholz [EMAIL PROTECTED] wrote:
 I'm not quite sure why this is illegal...

 foo :: Integer - (forall a. Show a = a)
 foo 2 = [foo]
 foo x = x

The type signature promises that foo returns a function that has type a
*for all a* (that are in Show). But neither a string list nor an integer
can have all types. Rather, they are very specific. That is, what you have
implemented actually could have type

foo :: Integer - (exists a. Show a = a)

(if GHC supported such types).

Note that only bottom can have a type like forall a.a.

 ...while this is just fine...

 bar :: Integer - (forall a. Show a = a-b) - b
 bar 2 k = k [bar]
 bar x k = k x

Here, you declare bar to *take* a function that delivers some b for any a.
That is, the burden of defining such a function now is on the caller, not
bar itself.

However, in this case, defining such an argument function actually is
easy, for another reason: the signature says k returns a result of type b,
but b is fixed. So it is always possible to come up with a trivial
instance of such a function (which will just ignore its argument). For
instance,

bar 2 (\_ - boo)

But try to call this for a different example:  ;-)

baz :: Integer - (forall a b. Show a = a-b) - c
baz 2 k = k [baz]
baz x k = k x

Hope this helps,
- Andreas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Type inference

2006-02-09 Thread Andreas Rossberg

Brian Hulley wrote:

Fred Hosch wrote:

Is type inferencing in Haskell essentially the same as in SML?


The most significant difference certainly is that type inference has 
been beefed up with type classes in Haskell, which are quite a powerful 
mechanism refining Hindley/Milner inference.


Besides that, Haskell allows some additional programs for which types 
can /not/ be inferred (e.g. the examples Brian was giving), while SML 
does not.


SML also has a complicated thing called the value restriction because 
it allows mutable references to be altered via side effects. Because 
Haskell has no side effects, there is no need for a value restriction.


Although there is no need for it, Haskell still has it, in minor 
variation. It is commonly known as The Dreaded Monomorphism 
Restriction ;).


  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: [Haskell] Dynamic binding

2005-06-24 Thread Andreas Rossberg

Ralf Lammel wrote:


Can you just tell how *you* would favor encoding the shapes example
that was posed by poster? (It might just be that your code would be
very close to Lennart's proposal?)


There is no universal answer. The shape example obviously is just a toy 
example. As long as I have no idea what *concrete* problem the original 
poster is trying to solve, I cannot really tell which approach is 
preferable for his endeavour. It seems more appropriate to describe the 
options and their trade-offs.


First of all, note that very often, you do not need a heterogeneous 
collection at all. Then plain polymorphism with type classes is more 
than enough, and more than OO provides in that situation.


In many cases where you need some kind of heterogenicity (is that a 
word?), the standard datatype approach shown by Lennart is perfectly 
suitable - in fact, often much more suitable than the OO solution. You 
know about the expression problem, and the two dual notions of 
extensibility? OO supports one dimension, datatypes the other. It 
depends on the problem which one is more important.


When you really need OO-style intensional kind of behaviour selection 
then first-class functions can bring you quite a long way, and often 
with much less amount of boilerplate than typical OO solutions.


When the behaviour you have to encapsulate in heterogeneous collection 
becomes more complex - say, more then just one or two functions - 
first-class functions can be tedious. Existential types represent a more 
coarse-grained and structured variant of the first-class function 
approach. They combine the power of first-class functions with the 
convenience of type classes, very similar to class-based objects. In 
these cases, they are the most appropriate solution.


Note again that with the latter two solutions, as with the OO approach, 
you do not have extensibility on the operations dimension.


Cheers,

  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Dynamic binding

2005-06-24 Thread Andreas Rossberg

Ralf Lammel wrote:



only because it's C-like :)  you just can't believe that Haskell
program can be 3-10 times smaller while keeping the same functionality
:)))


But note that same functionality is one thing,
having separate compilation and program extensibility too
is another one.


As I said, and as is well-known, extensibility is a red herring in 
this context - you merely trade one dimension of extensibility for 
another one.


Cheers,

  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Dynamic binding

2005-06-24 Thread Andreas Rossberg

Ralf Lammel wrote:


I would like to add a peer-reviewed clear reference
to the OOHaskell paper about the red herring that you mention.
I don't have such a reference. May I kindly ask you to offer
a few for selection?


Off-hand, I recall a paper by Martin Odersky and the Scala people 
discussing their approach to the Expression Problem, and a related paper 
by Jacques Garrigue, where he proposes to solve it using OCaml's 
polymorphic variants. Both should be easy to dig up with Google, and 
probably contain further pointers.


Hope this helps,

  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell] Dynamic binding

2005-06-23 Thread Andreas Rossberg

Andrew Ward wrote:
In Simon Thompson's The Craft of Functional Programming Second Edition, 
page 226, it is mentioned that Laufer (1996) describes a Haskell 
extension to allow dynamic binding. I was wondering if this has been 
implemented as an extension in any of the haskell compilers, or variants?


Definitely. GHC and Hugs implement it, don't know about the others.

But note that you do not necessarily need it. Often a simple first-class 
function, or a record thereof, is enough (in fact, dynamic binding is 
just the OOO way of saying calling a first-class function). In typical 
functional programming style, you need the general thing only rarely.


Cheers,

  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Dynamic binding

2005-06-23 Thread Andreas Rossberg

Ralf Lammel wrote:



dynamic binding is just the OOO way of saying
calling a first-class function).


Let me presume that dynamic binding 
was meant here in the sense of late binding


Yes.


in the sense of subtyping polymorphism.


No, as far as I read it, dynamic or late binding is orthogonal to 
subtyping, or typing in general. It is just that most typed OO languages 
lump these concepts together.


For me, dynamic or late binding just means calling (or more 
generally, accessing) something that is not determined statically. That 
is precisely what first-class functions provide.


Objects just turn more complex uses of this idiom into a language 
concept. Operationally, objects are equivalent to records of first-class 
functions. They usually come with more flexible typing and more 
efficient implementation, though.



(First-class function seems to refer to currying or what?)


No, constructing closures, and passing them around as values (currying 
is merely a particularly convenient special case of this).



(Did you miss a polymorphic before function? That would explain it.


I don't understand what you mean. Polymorphism is about typing. Late 
binding is not dependent on typing (there are untyped OO languages, for 
example).


Cheers,

  - Andreas

[Followups to Haskell Cafe]

--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] translation of kind

2005-06-20 Thread Andreas Rossberg

Ralf Hinze wrote:


I'ld prefer der Kind (and avoid situtations that allowed confusion
with das Kind)


Honestly, this is truly horrible (sorry, Peter). Just try to read it
aloud: der Kind des Typkonstruktors 


Indeed. Moreover, my impression is that many Germans rather tend to say 
die Kind instead when they have to, maybe because that is the gender 
you have for Sorte, Art, and Gattung.


--
Andreas Rossberg, [EMAIL PROTECTED]

Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Rank-N types vs existential types

2005-04-27 Thread Andreas Rossberg
Andre Pang wrote:
data RankN  = RankNEq (forall a. Eq a = a - a - Bool)
| RankNOrd (forall a. Ord a = a - a - Bool)
data Exists = forall a. Eq a = ExistsEq (a - a - Bool)
| forall a. Ord a = ExistsOrd (a - a - Bool)
So, the RankN type uses rank-2 polymorphism to hide the expression 
inside the type, whereas the Exists type uses existentially quantified 
types instead.  The two seem pretty equivalent to me, since the data 
constructors have the same type.  However, I can't help but feel that 
I'm missing something fundamental about a difference between them.  Are 
the two completely isomorphic?  Is there some advantage or disadvantage 
to using one over the other?
They don't have the same type. The types are
  RankNEq  :: (forall a.Eq a = a-a-Bool) - RankN
  ExistsEq :: forall a.Eq a = (a-a-Bool - Exists)
These are quite different beasts.
The difference really shows up when you *use* (deconstruct) them:
  g (RankNEq f) = (f 4 5, f True False)
This allows the embedded function to be used polymorphically. But:
  h (ExistsEq f) = ???
Here, you cannot use f at all (well, except with undefined). The type is 
not polymorphic in a on the RHS, it is abstract! You'd need to 
encapsulate a value of the same type (or a constructing function) as 
well to this type useful.

--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] MPTCs and type inference

2005-04-26 Thread Andreas Rossberg
Thanks for the detailed explanation that helped clearing up the smog in 
my head. I reckoned that once more the MR was to blame, at least for 
part of it.

in particular, when I compare with the single parameter case:
  class C a where fc :: a - a - ()
  c1 x = let p = fc x in ()
  c2 x = let p y = fc x y in ()
where
  c1 :: C a = a - ()
  c2 :: C a = a - ()
is inferred, as I would expect.
The inference steps for this case are much the same except, that the
inferred type for p now will be: a - (), provided that we can
solve the constraint C a.  Because we have assumptions about a in
the environment (namely it is mentioned in the type of the varible
x) we cannot generalize the type of p.  It therefore remains
monomorphic, and the constraint C a is propagated to the type of
c2.
To be more precise, p is not polymorphic *in the variables mentioned by 
the constraint* - the overall type of p could still be polymorphic, 
without changing the outcome.

My understanding now is as follows: a constraint is captured by a 
declaration if at least one of the type variables mentioned in the 
constraint is generalised in the respective type scheme. Is that a 
correct interpretation?

Of course, this is not the only possible rule. Alternatively, 
generalisation could always capture *all* unresolved constraints. For 
example, the type of p in c2 could be C a = a-() without a being 
quantified. That looks a bit more uniform in the face of MPTCs and would 
allow more programs, because contexts induced by dead code in form of an 
unused declaration could be forgotten consistently, not just when some 
of its free variables happen to be bound by a local quantifier.

--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


[Haskell] MPTCs and type inference

2005-04-25 Thread Andreas Rossberg
This may well be stupidity on my side, but some experiments with multi 
parameter type classes got me slightly confused. Can somebody explain 
the following behaviour to me?

  class D a b where fd :: a - b - ()
  d1 x = let p = fd x in ()
  d2 x = let p y = fd x y in ()
GHC derives the following types:
  d1 :: D a b = a - ()
  d2 :: a - ()
Hugs rejects d1 on the grounds that the type is ambiguous, but agrees on 
the type of d2. I do not understand where the context disappears to in 
this example - in particular, when I compare with the single parameter case:

  class C a where fc :: a - a - ()
  c1 x = let p = fc x in ()
  c2 x = let p y = fc x y in ()
where
  c1 :: C a = a - ()
  c2 :: C a = a - ()
is inferred, as I would expect.
--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell-cafe] Re: Pure Haskell Printf

2004-11-16 Thread Andreas Rossberg
Keean Schupke wrote:
Remember C is typesafe
In which parallel universe?
--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Pure Haskell Printf

2004-11-16 Thread Andreas Rossberg
Keean Schupke wrote:

I of course meant strongly-typed, you cannot pass a pointer to an int 
where a pointer
to a float is required ... modern C compilers require you to explicitly 
cast.
According to the C standard,
  void f(float *p) { *p + 1.0; }
  void g(void *p) { f(p); }
  void h(int n) { g(n); }
is perfectly valid (though undefined).
Where
it fell down was all that automatic type promotion, and providing unsafe 
casts.
And other things, like unions, varargs, etc. Not to speak of subtyping 
in C++...

There is now a typesafe 'C', but I can't remember what it is called - 
presumably it uses some kind of linear-alias typing to make pointers safe.
Do you mean Cyclone?
  http://www.research.att.com/projects/cyclone/
Cheers,
- Andreas
--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] mutually recursive modules

2004-09-24 Thread Andreas Rossberg
Alastair Reid wrote:
Generating .hiboot files by just deleting function definitions fails if there 
is no prototype for an exported function.  A crude approach is to assume the 
type (\forall a. a) for any function with no prototype but, although this is 
sound (I think), it will cause valid programs to be rejected.
Huh? How can that ever be sound? Are you sure you didn't mean (\exists a.a)?
- Andreas
--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] not getting most general type - is this a bug in hugs?

2004-07-29 Thread Andreas Rossberg
[EMAIL PROTECTED] wrote:
rep0' :: [Integer]-- WHAT??
You just have made first contact with the Dreaded Monorphism Restriction.
--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell] Per-type function namespaces (was: Data.Set whishes)

2004-03-04 Thread Andreas Rossberg
Simon Peyton-Jones wrote:
If the big bug-bear is record selectors, let's focus on them
exclusively.  I now think that ML got it right. ML records are simply
labelled tuples.
Note that this is true only for SML, not for Caml.

So just as (Bool,Int) is an anonymous type, so is
{x::Bool, y::Int}.  Indeed (Bool,Int) is just shorthand for {#1::Bool,
#2::Int}.
A bit of nitpicking: (Bool,Int) would be shorthand for {1::Bool,2::Int}. 
In SML, labels may be numeric or alpha-numeric. OTOH, the hash is the 
projection operator (ASCII art for \pi), which can be used for both 
kinds of labels:

  #2 (x,y,z)
  #b {a=x, b=y, c=z}
Actually, #l is just syntactic sugar for (\{l=x,...}-x), which implies 
that you might need type annotations.

There are
no implicitly-defined record selectors either: you have to use pattern
matching for that.
Or projection using #.

Cheers,

	- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Per-type function namespaces (was: Data.Set whishes)

2004-03-04 Thread Andreas Rossberg
Simon Peyton-Jones wrote:
| Actually, #l is just syntactic sugar for (\{l=x,...}-x), which
implies
| that you might need type annotations.
Yes I was wrong to say that there are no implicitly-defined record
selectors; (#l r) is exactly that.  Syntactically I'd prefer (r.l); but
regardless, it's a syntactic construct distinct from function
application, which must be monomorphic.
I'm not sure I parsed your sentence correctly, but in SML, (#l r) indeed 
*is* a function application, and #l is a perfectly normal function, as 
its desugared form reveals. It just fails to have a principal type (due 
to the lack of row polymorphism), so its type must be derivable from 
context - which might involve a type annotation.

BTW, I'd prefer r.l as well. A section like (.l) could then give you the 
equivalent of #l.

	- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Let's get rid of those possible thingies!  -- TB

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Re: Use of tab characters in indentation-sensitive code

2004-01-26 Thread Andreas Rossberg
George Russell wrote:
Graham Klyne wrote (according to Wolfgang Thaller, snipped):
  I think that compilers should issue a warning when indentation that
  determines the scope of a construct is found to contain tab characters.
In an ideal world, TAB characters would never have been put into ASCII, and
this would be my preferred solution.  However, since there would be some 
people
who would object to such purity, a better alternative might be
(a) to allow
m TABs followed by n spaces
at the start of lines.
(b) to denote the indention of the line by the two numbers (m,n).
(c) to give an error message when comparing two indentions 
(m1,n1),(m2,n2) where
neither m1=m2,n1=n2, nor m1=m2,n1=n2.

Incidentally Unicode allows far more possibilities for fun with 
indentation (for example
half-spaces, IIRC).
The most flexible but safe solution is to simply define the indentation 
as the sequence of indentation characters used. Two consecutive lines 
are indented consistently whenever one indentation is a prefix of the 
other. Hence you may freely mix different indentation characters, but 
you must be consistent across lines. Any decent editor should be able to 
ensure that.

With this solution, tab width is irrelevant and indentation may include 
whatever Unicode has.

	- Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Computer games don't affect kids; I mean if Pac Man affected us
 as kids, we would all be running around in darkened rooms, munching
 magic pills, and listening to repetitive electronic music.
 - Kristian Wilson, Nintendo Inc.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Gallopping Tab characters

2004-01-26 Thread Andreas Rossberg
George Russell wrote:

 The most flexible but safe solution is to simply define the indentation
 as the sequence of indentation characters used. Two consecutive lines
 are indented consistently whenever one indentation is a prefix of the
 other. Hence you may freely mix different indentation characters, but
 you must be consistent across lines. Any decent editor should be 
able to
 ensure that.

Well no they won't, because some editors might replace blocks of 8 spaces
at the start of a line with TABs (or something like that), meaning that
8 and 7 spaces would go to \t and, which your algorithm would
reject.


If the editor does the replacement consistently everywhere (like I would 
expect) then it would not change the meaning of a well-indented program.

   - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Computer games don't affect kids; I mean if Pac Man affected us
as kids, we would all be running around in darkened rooms, munching
magic pills, and listening to repetitive electronic music.
- Kristian Wilson, Nintendo Inc.


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes and code generation

2003-06-17 Thread Andreas Rossberg
Bayley, Alistair wrote:
When it's applied, the compiler will know the types of the arguments, won't
it?. Which means that you would generate a version of double for each
(applied) instance of Num. I don't doubt that there's a good reason this is
not done: code bloat? or are there simply some expressions that can't be
statically resolved?
I suppose I was thinking: is the language design sufficiently clever that
it's *always* possible for the compiler to infer the type instance in use,
or are there some situations where it's not possible to infer the instance,
so some kind of function dispatch mechanism is necessary?
This almost is an FAQ. Short answer: in general it is impossible to 
determine statically which instances/dictionaries are needed during 
evaluation. Their number may even be infinite. The main reason is that 
Haskell allows polymorphic recursion.

Consider the following (dumb) example:

f :: Eq a = [a] - Bool
f [] = True
f (x:xs) = x == x  f (map (\x - [x]) xs)
The number of instances used by f depends on the length of the argument 
list! Determining that statically is of course undecidable. If the list 
is infinite, f will use infinitely many instances (potentially, 
depending on lazy evaluation).

Another (non-Haskell-98) feature that prevents static resolution of type 
class dispatch are existential types, which actually provide the 
equivalent to real OO-style dynamic dispatch.

Of course, for most practical programs, the optimization you have in 
mind would be possible. I doubt compilers generally do it globally, 
though, because it requires whole program analysis, i.e. does not 
interfer well with separate compilation (beside other reasons).

| Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Computer games don't affect kids; I mean if Pac Man affected us
 as kids, we would all be running around in darkened rooms, munching
 magic pills, and listening to repetitive electronic music.
 - Kristian Wilson, Nintendo Inc.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: forall quantifier

2003-06-05 Thread Andreas Rossberg
Ketil Z. Malde wrote:
I have a function declared as:

  anova2 :: (Fractional c, Ord b)
= [a-b] - (a-c) - [a] - [Anova1 c]
where the first parameter is a list of classifiers.  I could simplify
it, I guess, to something like
  classify :: Eq b = [a-b] - [a] - [[[a]]]
   ^^^
Isn't this one list too many?
  classify cs xs = ...

where for each classifying function in cs, I would get the xs
partitioned accordingly.  E.g.
  classify [fst,snd] [(1,0), (1,2), (2,0)] 

would yield

  [ [(1,0), (1,2)], [(2,0)] -- classified by `fst`
  , [(1,0), (2,0)], [(1,2)]] -- classified by `snd`
Now, obviously, the problem is that fst and snd, being passed in a
list, needs to be of the same type; this complicates classifying a
list of type [(Int,Bool)], for instance?.
What you'd need would be an existential type of the form

   classify :: [exists b. Eq b = a-b] - [a] - [[a]]

Such a type is not available directly in Haskell, but only through an 
auxilary data type:

  data Classifier a = forall b. Eq b = Classifier (a - b)

Using that you should be able to implement

   classify :: [Classifier a] - [a] - [[a]]

Cheers,

  - Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
Computer games don't affect kids; I mean if Pac Man affected us
 as kids, we would all be running around in darkened rooms, munching
 magic pills, and listening to repetitive electronic music.
 - Kristian Wilson, Nintendo Inc.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: beginner's questions - fix f

2001-07-24 Thread Andreas Rossberg

Bob Koutsky wrote:
 
 remainder a b = if a  b then a
  else remainder (a-b) b
 
 fix f = f (fix f)
 
 Rewrite remainder using fix so that it is not recursive.
 
 
 Function fix left me completely puzzled. With help of hugs I found out that
 its type is ( a - a ) - a, but I have absolutely no idea how it could
 be used to do anything useful.

Function fix is a so-called fixpoint operator. Theory says that you can
formulate any computable function using only non-recursive definitions
plus fix.

 Can somebody provide me
 with an example how to use fix for something just a bit useful, if possible
 to rewrite remainder?

Try:

remainderF self a b = if a  b then a else self (a-b) b

remainder = fix remainderF

From this example it is easy to infer how to transform arbitrary
recursive definitions. Even generalising it to mutual recursion is not
difficult (and left as an exercise to the reader ;-).

All the best,

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

Computer games don't affect kids.
 If Pac Man affected us as kids, we would all be running around in
 darkened rooms, munching pills, and listening to repetitive music.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Inferring from context declarations

2001-02-22 Thread Andreas Rossberg

Lennart Augustsson wrote:
 
 Incidentally, this has nothing to do with allowing polymorphic recursion
 on functions in Haskell.  It could be done earlier too, but then it had
 to be encoded using a class and instance declaration.

I would argue that methods are in fact polymorphically recursive
functions. Wasn't this one motivation to allow general polymorphic
recursion in Haskell - that it is in the language anyway?

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

"Computer games don't affect kids.
 If Pac Man affected us as kids, we would all be running around in
 darkened rooms, munching pills, and listening to repetitive music."

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Doing IO in foldr repeats lines?

2001-01-23 Thread Andreas Rossberg

Ian Lynagh wrote:
 
  main :: IO()
  main = do _ - foldl foo (return 14) ["qq\n", "ww\n", "ee\n"]
putStr ""
 
  foo :: IO Int - String - IO Int
  foo io_l s = do l - io_l
  () - putStr s
  io_l
 
 prints (with both GHC and hugs):
 
 qq
 ww
 qq
 ee
 qq
 ww
 qq
 
 and I really don't understand why. Is the code re-evaluated every time
 foldl is expanded or something?

Nobody seems to have answered yet, so I try to explain it.

Look at your definition of foo: it actually duplicates its argument
action io_l. For the first application io_l is (return 14). Let's call
that io_l0. The resulting action is

io_l1 = do { l - return 14; () - putStr "qq"; return 14 }

which is passed at the next application. The result is

io_l2 = do { l - do { l - return 14; () - putStr "qq"; return 14 }
   ; () - putStr "ww"
   ; do { l - return 14; () - putStr "qq"; return 14 }
   }

This can be reformulated as

io_l2'= do { l  - return 14
   ; () - putStr "qq"
   ; l  - return 14
   ; () - putStr "ww"
   ; l  - return 14
   ; () - putStr "qq"
   ; return 14
   }

And so on. Finally the complete action (io_l3) is executed by running
main and produces the output you observe.

Hope this helps,

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: class instance with nested types

2000-10-27 Thread Andreas Rossberg

Matthias Höchsmann wrote:
 
  type Sequence a = [a]
  data Tree a = N a (Forest a) deriving (Ord,Eq,Show)
  type Forest a = Sequence (Tree a)
 
 i want to construct a class Xy
 
  class Xy s a where
   test :: s a - a
 
 [...]
 
  instance  ([] Tree) Char where
  test x@(N a xs):txs = a

To make it syntactically correct this should at least be something like

 instance Xy ([] Tree) Char where
 test (N a xs:txs) = a

But the real problem is in the expression ([] Tree), which is the same
as writing [Tree]. This is not a legal type expression, since Tree is a
type constructor, not a ground type, so you cannot apply it to the list
constructor.

What you are trying to say is probably something like this:

 instance Xy (\a . [Tree a]) Char  -- not Haskell

But unfortunately there are no lambdas on the type level - they would
render the type system undecidable. For the same reason it is not
allowed to use a type synonym in an instance declaration:

 instance Xy Forest Char   -- illegal

The only thing you can do is turning Forest into a data type:

 data Tree a = N a (Forest a) deriving (Ord,Eq,Show)
 data Forest a = Forest [Tree a]
 
 instance Xy Forest Char where
 test (Forest (N a xs:txs)) = a

HTH,

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: class instance with nested types

2000-10-27 Thread Andreas Rossberg

I mumbled:
 
 This is not a legal type expression, since Tree is a
 type constructor, not a ground type, so you cannot apply it to the list
 constructor.

The other way round, of course: you cannot apply the list constructor to
it.

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Compiler implementation and FP [Was: Re: Clean and Haskell]

2000-01-13 Thread Andreas Rossberg

"Frank A. Christoph" wrote:
 
 It seems to me that a compiler would be an ideal candidate for being written
 in an imperative language. The number of times GHC has been too slow and
 memory-hungry for me indicates that Haskell is not suitable for writing
 anything as general-purpose as a compiler.

 Food for thought. :) I'm in an equivocal mood tonight...

[OK, I'll jump in :-)]

Of course, the first sentence is an invalid generalization. It may (or
may not -- I hope time will prove you wrong and Haskell code will
improve performance-wise) be true that Haskell is not suitable for
writing compilers. But this does not imply that FPLs in general are not
suitable for writing compilers -- or even less suitable than imperative
languages...

It seems to be folklore in the FP community that functional languages
are perfect for this task. After all, it is what they are mainly used
for :-|. I wouldn't dare writing such a beast without pattern matching,
higher-order functions, a powerful type system, and strong support for
recursion -- things imperative languages usually lack completely. OTOH I
have to admit that imperative features come in handy sometimes (eg. for
unification) -- like always.

Compilers like OCaml or SML/NJ are very fast, even though they have to
perform quite some complex stuff. And they are `mostly functional'.

(And please: not another flame war about the definition of
`functional'.)

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::



Re: Units of measure

1999-08-26 Thread Andreas Rossberg

Tom Pledger wrote:
 
 Where do units of measure fit into a type system?

In Haskell this should be quite easy. Off my head I would suggest
something like

class Unit a where
unit  :: Float - a
value :: a - Float

newtype Metres  = Metres Float
newtype Seconds = Seconds Float

instance Unit Metres where
unit = Metres
value(Metres x) = x
instance Unit Seconds where
unit = Seconds
value(Seconds x) = x

newtype Prod a b = Prod Float
newtype Quot a b = Quot Float

instance (Unit a, Unit b) = Unit(Prod a b) where
unit = Prod
value(Prod x) = x
instance (Unit a, Unit b) = Unit(Quot a b) where
unit = Quot
value(Quot x) = x

infix 7 *$, /$
infix 6 +$, -$

(+$) :: (Unit a) = a - a - a
(-$) :: (Unit a) = a - a - a
(*$) :: (Unit a, Unit b) = a - b - Prod a b
(/$) :: (Unit a, Unit b) = a - b - Quot a b
x +$ y = unit(value x + value y)
x -$ y = unit(value x - value y)
x *$ y = Prod(value x * value y)
x /$ y = Quot(value x / value y)

m  = Metres 5
s  = Seconds 2
m' = m +$ m -- OK: Metres
m2 = m *$ m -- OK: Prod Metres Metres
v  = m /$ s -- OK: Quot Metres Seconds
a  = m /$ (s *$ s)  -- OK: Quot Metres (Prod Seconds Seconds)
x  = m -$ s -- error

It would be nicer if Haskell had infix type constructors:

   newtype a :* b = Prod Float
newtype a :/ b = Quot Float

Cheers,

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::





Re: Units of measure

1999-08-26 Thread Andreas Rossberg

"D. Tweed" wrote:
 
 Isn't the issue a bit weirder than this in that you've also got pure
 numbers which ought be usable with the same operators (*$,etc)

You are right, I overlooked that. But this is not even the most serious
problem, overloading the operators accordingly might be possible with
MPTCs, I think. The hard problem is that you cannot establish equalities
like

Prod a (Quot b a)  =  b

Sigh.

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::





Re: The dreaded layout rule

1999-08-12 Thread Andreas Rossberg

Simon Marlow wrote:
 
  Does it mean that the following expressions would be illegal?
 
  if cond then do proc1; proc2 else do proc3; proc4
  (case e of Just x - x  0; Nothing - False)
 
 Unfortunately, yes.
 
  Now one can forget about {} and use layout everywhere. He would no
  longer be able to forget or he would have to split some expressions
  into indented lines, even when they are unambiguous in one line.

You could just enumerate all keywords that allow/enforce insertion of }.
A suitable list for Haskell 98 might be:

in
where
)
]
module
type
data
newtype
class
instance
default

In fact I think that this would be the cleanest and simplest rule. (At
least that is how I once implemented layout similar to Haskell's,
because I couldn't get Yacc's error productions to work properly in all
cases).

For Haskell 2(000) I would suggest removing all but the first 4 tokens
from the list above.

- Andreas

-- 
Andreas Rossberg, [EMAIL PROTECTED]

:: be declarative. be functional. just be. ::





Re: Simon's H98 Notes

1998-10-22 Thread Andreas Rossberg

Frank A. Christoph wrote:
 
 Standard ML does not allow this. One important aspect of the SML module
 system actually is its strong separation from the core language.
 
 Not that old saw again...!  Ocaml separates the two as well.

Well, the new let-module feature undermines the separation quite a bit,
because any expression can now contain arbitrary module code -- the
module system no longer rests on top of the core language.

 I imagine that it could be translated into SML along these lines
 (excuse my rusty SML):
 
   structure M = struct ... val y = ref something ... end;
   structure X =
 struct
   fun f(x,y) = M.y := y; ... !M.y ...
 end;
 
 Or maybe not.  I'm not sure of the extent of the feature, but I get the 

Not really. First of all, f will not be re-entrant (e.g. recursion won't
work). You had to save and restore the previous value. But that's not
all: consider the following (admitedly contrieved) code for example

let rec f x = let module M = struct exception E end
  in match x with M.E - ()
| _   - f M.E

A call like f(some_exn) will not terminate because M.E is different on
each recursion. You can observe similar effects using references. The
point here is that modules (and all the generative objects in it, like
references, exceptions, modules, etc.) are really created at runtime,
while without the let-module feature, all module instances are
determined at compile time.

Also, the main motivation for introducing it was to allow functor
applications that depend on polymorphic type variables. I think these
cannot be translated (as far as typing is concerned).

(In case somebody is still interested. But this has far left the scope
of the Haskell list now.)


 You're right, though.  I meant expression-local imports, like
 
   local open M
   in ...

\begin{nitpicking}

You probably mean

let open M
in ...

\end{nitpicking}

And I agree, these are very useful sometimes (although I wouldn't call
that import).

- Andreas





Haskell 98 - The Underbar

1998-10-19 Thread Andreas Rossberg

Ralf Hinze wrote:

* make '_' lexically a valid identifier character anywhere
* but disallow identifiers starting with '_'
 
 Thus '___' would lex as '___' but then be rejected. '_' on its own remains a
 wild-card pattern, and illegal in expressions.
 
 
 ] `_' is a special case whatever option one chooses. So I can see no real
 ] advantage in disallowing identifiers starting with '_'.

IMHO the simplest rule would be to allow '_' anywhere a lowercase letter
is
allowed. And "_" becomes just an ordinary keyword.

Cheers,
- Andreas





Re: Multi-parameter type classes

1998-06-30 Thread Andreas Rossberg

Simon L Peyton Jones wrote:
 
 GHC 3.02 supports multi-parameter type classes, but I have been
 guilty of not documenting precisely what that means.
 
 I've now summarised the extensions, informally but I hope
 precisely, at
 
 http://www.dcs.gla.ac.uk/multi-param.html

That does not seem to be the correct URL. I had better luck with:

http://www.dcs.gla.ac.uk/~simonpj/multi-param.html


- Andreas





Re: Punning: Don't fix what ain't broken.

1998-02-12 Thread Andreas Rossberg

Tommy Thorn wrote:
 
 Koen Claessen:
  This brings us to another issue. Doesn't the following definition look
  a bit awkward?
 
R{ x = x }
 
 Definitely wierd.  The left and right-hand side denotes two different
 things, which AFAIK is the only place where `=' behaves like this.
 Wouldn't `-' have been a better choice?  `-' bindings are never
 recursive, thus `R{ x - x } is less surprising, as the two x's can't
 be the same.


What about using constructor syntax: R{ X x } ?

Not to be taken too seriously...

- Andreas