<div dir="ltr">I've been thoroughly kicking the tires on the subtyping feature of Mercury ... and I've been learning a lot in the process ... including some of the nuances of how the inst and mode system works.<br><br>I was initially confused as to how to safely coerce a supertype down to a subtype, struggling with how to get a variable bound to the inst tree of the subtype, rather than just ground in a semi deterministic manner.   I'd forgotten some of the expressive power of the mode system.<br><br>What I learned is that you can use a mode to make that transformation of the inst to allow the safe coercion.<br><br>:- type foobar<br>  --->  foo<br>  ;  bar.<br><br>:- inst foo ---> foo.<br><br>:- type foo =< foobar ---> foo.<br><br>:- mode is_foo == ground >> foo.<br><br>:- pred is_foo(foobar::is_foo) is semidet.<br><br>is_foo(Foo) :- Foo = foo.<br><br>:- func downcast_foo(foobar) = foo is semidet.<br><br>downcast_foo(Foo) = coerce(Foo) :- is_foo(Foo).<br><br>It took me far too long to realize I could use a mode such as is_foo/0 to tell the mode checker that a variable was safe to coerce to a subtype.</div>