Nice 
Author Message
 Nice

Has anyone here tried Nice?
    http://www.*-*-*.com/

It looks like Java with a bunch of nice (hehe) features,
some from functional languages, including first-class
functions, parametric polymorphism, multiple dispatch, and
no casts.

I'm not much of a Java programmer, so I doubt I'd be using
this any time soon, but it looks kind of cool and vaguely
on-topic here.

Jesse



Sun, 01 Jan 2006 03:21:54 GMT  
 Nice

Quote:

> Has anyone here tried Nice?
>    http://nice.sourceforge.net/index.html

> It looks like Java with a bunch of nice (hehe) features,
> some from functional languages, including first-class
> functions, parametric polymorphism, multiple dispatch, and
> no casts.

It's a nice little language, though a first reading of the material on
the source forge site revealed the following weaknesses:

1) No sum types (did I get the name right?). There's a special
constructor called ? that additionally allows the Null value (i.e.
?String is essentially equivalent to Some String), but that's all.
This is a deliberate decision, based on the idea that it's easier to use
than sum types. (Personally, I find that idea mistaken: SQL has shown
that a single Null value usually doesn't express exactly what's meant,
resulting in all kinds of confusion of what Null actually means.)

2) Multiple dispatch without a safety net. (This is a problem that's
specific to dynamic dispatch based on subtypes, so off-topic in this group.)
I think this is an oversight by the designer. (It's a hairy problem
though. No really satisfactory solutions exist.)

3) The designer states that "These languages are doing very well as far
as static safety is concerned. However, they achieve this safety by
enforcing a quite different programming style. This makes it difficult
to compare expressiveness, and definitely compromises their chances of
becoming used widely."
I believe this is partly true, though the wording is a bit strong...

HTH
Jo



Sun, 01 Jan 2006 08:45:34 GMT  
 Nice

Hi,

As the main author of the language, I thought I could provide some comments.

Quote:
> 1) No sum types (did I get the name right?).

You can get a similar behaviour with classes. For instance, instead of

type 'a list = Nil | Cons of 'a * 'a list;

you can declare

abstract class List<T> {}
class Nil<T> extends List<T> {}
class Cons<T> extends List<T> { T head; List<T> tail; }

One advantage is that Cons<T> is a type. Therefore the tail operation is
total, of type <T> Cons<T> -> List<T>, while it is usually partial in
traditional functional languages.

A major difference is that sums represented by class hierachies are
"open": you can add after the fact a new case, for instance
class Append<T> extends List<T> { List<T> start; List<T> end; }
which allows constant-time concatenation.

Closed sums will be made available soon, by adding the (type safe) enum
construct, which is in a way the dual of the class construct.

Quote:
> This is a deliberate decision, based on the idea that it's easier to use
> than sum types.

Not exactly. '?' was added to be able to use null in a type safe way. It
is indeed similar to a sum type, but its special structure allows for a
more convenient use. In particular, there is a subtyping between T and
?T (that is, a value of type string can be used where a string option is
expected, without manual wrapping in the Some constructor).

Quote:
> (Personally, I find that idea mistaken: SQL has shown
> that a single Null value usually doesn't express exactly what's meant,
> resulting in all kinds of confusion of what Null actually means.)

This is a valid concern. When designing a program, a choice can be made
between using an option type, or a full-blown sum type (either class or
enum). But even if you decide never to use option types, they can come
handy when using APIs written in Java.

Quote:
> 2) Multiple dispatch without a safety net. (This is a problem that's
> specific to dynamic dispatch based on subtypes, so off-topic in this
> group.)
> I think this is an oversight by the designer. (It's a hairy problem
> though. No really satisfactory solutions exist.)

Can you precise what you mean by safety net?
Nice is statically type-safe, and is type-checked modularly.

Quote:
> 3) The designer states that "These languages are doing very well as far
> as static safety is concerned. However, they achieve this safety by
> enforcing a quite different programming style. This makes it difficult
> to compare expressiveness, and definitely compromises their chances of
> becoming used widely."
> I believe this is partly true, though the wording is a bit strong...

I'm sorry if I hurt feelings with that sentence. I merely meant to say
that Nice, compared with most research languages, has a slightly
different trade-off between compatibility with mainstream programming
style and introduction of new concepts. The handling of option types is
one such example.

Daniel



Sun, 01 Jan 2006 21:13:10 GMT  
 Nice

Quote:

>> 1) No sum types.

> You can get a similar behaviour with classes. For instance, instead of

> type 'a list = Nil | Cons of 'a * 'a list;

> you can declare

> abstract class List<T> {}
> class Nil<T> extends List<T> {}
> class Cons<T> extends List<T> { T head; List<T> tail; }

Well, the point is that a sum type is declared on-the-fly as needed.
Your code is admirably short for declaring an entire class, but the sum
type declaration is still shorter.

Of course, this is mainly an argument about what patterns are more
common and important, something that can be decided only in a serious
discussion.

Quote:
> One advantage is that Cons<T> is a type. Therefore the tail operation is
> total, of type <T> Cons<T> -> List<T>, while it is usually partial in
> traditional functional languages.

It's not too relevant whether the "tail" of a list is Null or Nil - the
only relevant detail here is that the end-of-list marker can be
distinguished from an inner list node.
Actually the Nil definition in the functional declaration above is
different from Void. It's just a type tag, and could have had any name.
E.g. I could equivalently define
   type 'a list = EndOfList | ListNode of 'a * 'a list;

Quote:
> A major difference is that sums represented by class hierachies are
> "open": you can add after the fact a new case, for instance
> class Append<T> extends List<T> { List<T> start; List<T> end; }
> which allows constant-time concatenation.

That's correct.

Quote:
> Closed sums will be made available soon, by adding the (type safe) enum
> construct, which is in a way the dual of the class construct.

>> This is a deliberate decision, based on the idea that it's easier to
>> use than sum types.

> Not exactly. '?' was added to be able to use null in a type safe way.

My point is not that '?' in itself is a problem, but that, in practice,
you often need more than one Null value. Which suggests that Null should
not be treated as Void, but just as a constructor that happens to have
no components.

More concretely: I might have
   type address =
     NotKnown | Irrelevant | String name * String first_name * ...
to differentiate between different forms of "no data available".

 From a language semantics standpoint, Void is just an enum that happens
to be predefined, with a single value.

 > It

Quote:
> is indeed similar to a sum type, but its special structure allows for a
> more convenient use. In particular, there is a subtyping between T and
> ?T (that is, a value of type string can be used where a string option is
> expected, without manual wrapping in the Some constructor).

The sum type construction would work just as well. The proper subtypes
of address are:
   NotKnown | String name * ...
   NotKnown | Irrelevant
   Irrelevant | String name * ...
   NotKnown
   Irrelevant
   String name * ...
In other words: wherever a routine expects an "address" object, you can
simply pass in the struct.
No need for a Some constructor anywhere I can see...

Quote:
> [...] But even if you decide never to use option types, they can come
> handy when using APIs written in Java.

If Java compatiblity is indeed a concern, then this is a very valid reason.
I'd still design Void as just another constructor, just for
orthogonality's sake.

Quote:
>> 2) Multiple dispatch without a safety net. [...]

> Can you precise what you mean by safety net?

I'll take this aspect into private discussion, as it's far off-topic of
comp.lang.functional.

Regards,
Jo



Mon, 02 Jan 2006 05:52:03 GMT  
 Nice

Quote:
> It's not too relevant whether the "tail" of a list is Null or Nil - the
> only relevant detail here is that the end-of-list marker can be
> distinguished from an inner list node.
> Actually the Nil definition in the functional declaration above is
> different from Void. It's just a type tag, and could have had any name.
> E.g. I could equivalently define
>   type 'a list = EndOfList | ListNode of 'a * 'a list;

There must have been a misunderstanding, because I completely agree with
this. Note that I explicitely declared the Nil class. The name is indeed
arbitrary. It had nothing to do with the null value.

Quote:
> My point is not that '?' in itself is a problem, but that, in practice,
> you often need more than one Null value. Which suggests that Null should
> not be treated as Void, but just as a constructor that happens to have
> no components.

My point was that Nice fully allows you to do that, as the Nil class for
lists shows.

'?' is there as a predefined type constructor, because it happens that
in Java many types implicitly contain the value null. In that case it
does not make sense to have several nulls, because that's something out
of your control.

Quote:
> The sum type construction would work just as well. The proper subtypes
> of address are:
>   NotKnown | String name * ...
>   NotKnown | Irrelevant
>   Irrelevant | String name * ...
>   NotKnown
>   Irrelevant
>   String name * ...
> In other words: wherever a routine expects an "address" object, you can
> simply pass in the struct.
> No need for a Some constructor anywhere I can see...

In that case the constructor is called String.

I was refering the the OCaml type
type 'a option = None | Some of 'a;

A string option is not a subtype of string, you have to manually wrap
the string using the Some constructor. On the contrary, in Nice, ?String
is a subtype of String.

Quote:
> If Java compatiblity is indeed a concern, then this is a very valid reason.
> I'd still design Void as just another constructor, just for
> orthogonality's sake.

In that case, how would you make String a subtype of "String option"?

Daniel



Tue, 03 Jan 2006 06:13:54 GMT  
 Nice

Quote:

>> Actually the Nil definition in the functional declaration above is
>> different from Void. It's just a type tag, and could have had any
>> name. E.g. I could equivalently define
>>   type 'a list = EndOfList | ListNode of 'a * 'a list;

> There must have been a misunderstanding, because I completely agree with
> this. Note that I explicitely declared the Nil class. The name is indeed
> arbitrary. It had nothing to do with the null value.

I probably misread some of the presentation on the web page.

Quote:
> '?' is there as a predefined type constructor, because it happens that
> in Java many types implicitly contain the value null. In that case it
> does not make sense to have several nulls, because that's something out
> of your control.

Fully agreed.

Quote:
>> The sum type construction would work just as well. The proper subtypes
>> of address are:
>>   NotKnown | String name * ...
>>   NotKnown | Irrelevant
>>   Irrelevant | String name * ...
>>   NotKnown
>>   Irrelevant
>>   String name * ...
>> In other words: wherever a routine expects an "address" object, you
>> can simply pass in the struct.
>> No need for a Some constructor anywhere I can see...

> In that case the constructor is called String.

No, I was a bit too short. I should have written (omitting syntactic sugar)
   AddressData = type
     String name
     String first_name
     String street
     ...
   end type
and the subtypes of "address" would then be NotKnown, Irrelevant,
AddressData, and any combination of these.

Quote:
> I was refering the the OCaml type
> type 'a option = None | Some of 'a;

Ah, now I understand your argument.

There are two ways to define an option type:
1) Define two struct types, such as None and Some. This indeed requires
an extra wrapping step.
2) If you know that None is not already in the domain of a type T,
define a new type with an extended domain; this could be written as
"None | 'a".

The second alternative is indeed not part of typical functional
languages: sum types cannot be extended by adding a declaration.

Does anybody in this newsgroup know why sum types are closed?

If no serious problems turn up, I'd make the mechanism more general in
Nice. And predefine ? as
   type ? X = Void | X
I'm not sure about cases where Void is already in X's domain. Either ?X
is the same as X (i.e. adding a value to the domain that's already in it
has no effect), or it's illegal (i.e. a value can be added to a domain
only once). I'm pretty sure there are ramifications for either decision,
but I think it's worth the trouble if one can get rid of a special rule.
(My experience is that special rules require the full analysis anyway,
so making it a general mechanism doesn't entail any extra design overhead.)

Quote:
> A string option is not a subtype of string, you have to manually wrap
> the string using the Some constructor. On the contrary, in Nice, ?String
> is a subtype of String.

Agreed.

Quote:
>> I'd still design Void as just another constructor, just for
>> orthogonality's sake.

> In that case, how would you make String a subtype of "String option"?

I was assuming the construction "None | String".

Regards,
Jo



Tue, 03 Jan 2006 15:32:24 GMT  
 Nice

On Fri, 18 Jul 2003 09:32:24 +0200

Quote:

> The second alternative is indeed not part of typical functional
> languages: sum types cannot be extended by adding a declaration.

> Does anybody in this newsgroup know why sum types are closed?

I was just thinking about this yesterday, actually.  The best guess I
could come up with is that it has to do with type inference.  If you had
the following code (in SMLish syntax):

datatype foo = A | B
datatype bar = foo | C

val baz = A

Now is baz of type foo or type bar?

Benjamin

  application_pgp-signature_part
< 1K Download


Tue, 03 Jan 2006 21:55:32 GMT  
 Nice

Quote:

> Does anybody in this newsgroup know why sum types are closed?

Because that is an essential prerequisite for the strong type checking
that we like so much, i.e. the luxury of exhaustiveness checks for
pattern matching.

Moreover, open/extensible/polymorphic sums are much more demanding with
respect to typing.

- Andreas

--

"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.



Tue, 03 Jan 2006 22:07:38 GMT  
 Nice
The type inference gets a bit tricker compare to closed sums, but it's
not a problem. OCaml provides for extensibles sum types. They call
them "polymorphic variants" if I'm not mistaken. Cyclone has
extensible sum types too. SML didn't probably because they didn't
think you need it at the time. Proposal for SML2000
had extensible sums.

Also, extensible sums are slightly harder to pattern match against
efficently as opposed to closed sums. You also loose some pattern
matching guarntees. (Is the match exhaustive?) and seperate
compliation gets more difficult.

Quote:

> On Fri, 18 Jul 2003 09:32:24 +0200

> > The second alternative is indeed not part of typical functional
> > languages: sum types cannot be extended by adding a declaration.

> > Does anybody in this newsgroup know why sum types are closed?

> I was just thinking about this yesterday, actually.  The best guess I
> could come up with is that it has to do with type inference.  If you had
> the following code (in SMLish syntax):

> datatype foo = A | B
> datatype bar = foo | C

> val baz = A

> Now is baz of type foo or type bar?

> Benjamin

> --



Wed, 04 Jan 2006 04:07:01 GMT  
 Nice

Quote:
> > I was just thinking about this yesterday, actually.  The best guess I
> > could come up with is that it has to do with type inference.  If you had
> > the following code (in SMLish syntax):

> > datatype foo = A | B
> > datatype bar = foo | C

> > val baz = A

> > Now is baz of type foo or type bar?

> > Benjamin

I don't know how any particular language does this, but I would say baz
_should_ be type foo.  Meanwhile, the language should allow functions
which take a bar type to receive a foo type object.

There are probably more complex cases which destroy type inferencing
but this case is easy.



Fri, 06 Jan 2006 09:30:33 GMT  
 Nice

Quote:

> I was just thinking about this yesterday, actually.  The best guess I
> could come up with is that it has to do with type inference.  If you had
> the following code (in SMLish syntax):

> datatype foo = A | B
> datatype bar = foo | C

> val baz = A

> Now is baz of type foo or type bar?

ocaml
# type foo = [`A | `B];;
type foo = [ `A | `B]
# type baz = [foo | `C];;
type baz = [ `A | `B | `C]
# let baz = `A;;
val baz : [> `A] = `A

It's explained in the ocaml manual, section 4.2.

Christoph Bauer

--
proc self {} {foreach c [split [info body self] ""] d {14 -7 0 0 4 -67 4 73 11
69 24 -83 -15 6 -4 -84 78 20 11 -78 -1 -1 79 19 -8 4} { binary scan $c c c
if {[catch {append r [format %c [expr $c+$d]]}]} {return $r};}};puts [self]



Fri, 06 Jan 2006 13:10:14 GMT  
 
 [ 21 post ]  Go to page: [1] [2]

 Relevant Pages 

1. NICE and NICE Discussion List

2. Nice Date

3. AD (Was: Nice Date

4. AD (Was: Nice Date...

5. AD (Was: Nice Date

6. Nice Idiom

7. A nice rtf2txt-converter for Dyalog 9

8. Nice webpage

9. Have a nice Smalltalk day in the alps

10. Nice Examples Site

11. VW: proposel for nicer Symbol>>keywords implementation

12. Nice icons

 

 
Powered by phpBB® Forum Software