On Tue, 19 Feb 2013, Chris Cannam wrote:
> On 22 January 2013 01:41, Madis <
ma...@cyber.ee> wrote:
>> I now implemented a bit smarter handling of such case expressions type - it
>> basically still gets extendable variant type, but flagged as also
>> narrowable. Seems like it should work.
>
> At the time I said that this seemed to work -- but I think I may have
> been checking too superficially.
>
>>> f = \case of B (): println "!!!"; _: () esac
>> f is B () -> () = <code$>
>>> g x = (println case x of A x: x; B (): "B" esac; f x);
>> g is A. string | B. () -> () = <code$g>
>>> g is (A. string) -> ()
>> <code$g> is A. string -> ()
>
> But now:
>
>> g (B ())
> B
> !!!
>
> in other words, the compiler reports the narrowed type but still
> accepts the wider type.
I guess the reason here is that g is polymorphic binding - using the
`is' result directly, or rebinding it with the restricted type gives the
binding also the restricted type.
> (g is A. string -> ()) (B ())
1:28: Cannot apply A. string -> () function to B () argument
Type mismatch: A. string => B () (member missing: B)
> g = g is A. string -> ()
g is A. string -> () = <code$g>
> g (B ())
1:7: Cannot apply A. string -> () function (g) to B () argument
Type mismatch: A. string => B () (member missing: B)
> It seems to do this for any function that accepts variant types
> regardless of whether there are any constructed types involved:
>
>> f x is (A number | B number) -> 'a = x
> f is A number | B number -> A number | B number = <code$f>
>> f (C 1)
> C 1 is A number
> | B number
> | C number
This is actually correct - you restricted the type by adding new required
tag C to the required variants set). Had the f x is type been about
accepted types, it would have worked differently:
> f x is (A. number | B. number) -> 'a = x
f is ('a1 is A. number | B. number) -> 'a1 = <code$f>
> f (C 1)
1:6: Cannot apply ('a0 is A. number | B. number) -> 'a0 function (f) to ('a0 is C number) argument
Type mismatch: ('a0 is A. number | B. number) => ('a0 is C number) (member missing: C)
The above shouldn't.
>> store = load yertle.store
>> s = store.newStore ()
> s is [yertle/store:store]<> = {indexes=[{order=[0,1,2],
> tree=[:]},{order=[1,2,0], tree=[:]},{order=[2,1,0], tree=[:]}]}
>> store.match
> <yertle.store$match> is [yertle/store:store]<> -> {
> o is Known (Blank number
> | IRI string
> | Literal {
> language is string,
> type is string,
> value is string
> }) | Wildcard (),
> p is Known (IRI string) | Wildcard (),
> s is Known (Blank number | IRI string) | Wildcard ()
The argument type seems incorrect - if only Known or Wildcard is
accepted, then those should be in type as Known. or Wildcard. (with dot at
the end). The index module type signature seems correct:
chooseIndex is list<index> -> array<('_g1 is Known. '_e1 | Wildcard. '_f1)> -> index,
match is ('s1 is {`order is list<number>, `tree is ('q0 is hash<'_p1, ('_r1 is Entry` pattern | Sub` 'q0)>)}) -> array<('_u1 is Known. '_p1 | Wildcard. '_t1)> -> list<pattern>,
But store's match is somehow broken - for some reason the following:
match is store -> pattern -> list<statement>.
is incorrectly unified into required (constructed value) tag set in the
Known. _ | Wildcard. _ part, while the result imho actually should be
Known` _ | Wildcard` _ - being both constructed and accepted tags.