Difference between revisions of "SyntaxFreeTypeDirectedNameResolution"

From HaskellWiki
Jump to navigation Jump to search
m
m
Line 1: Line 1:
= Proposal: Syntax-Free Type Directed Name Resolution =
 
 
 
The original [http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution TDNR proposal] was fairly controversial, with almost all of the objections related to the new dot syntax. However, TDNR can be implemented without any changes to the syntax of Haskell and without adding any new operators.
 
The original [http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution TDNR proposal] was fairly controversial, with almost all of the objections related to the new dot syntax. However, TDNR can be implemented without any changes to the syntax of Haskell and without adding any new operators.
   
== Disambiguation ==
+
= Disambiguation =
   
 
When GHC encounters an ambiguous name (i.e. imported from different modules without qualification), it will create a constraint for the name's type from available type information. If exactly one candidate definition matches this type constraint, it will be selected.
 
When GHC encounters an ambiguous name (i.e. imported from different modules without qualification), it will create a constraint for the name's type from available type information. If exactly one candidate definition matches this type constraint, it will be selected.
Line 13: Line 11:
 
# The inferred type of the name's argument. The compiler will attempt to infer the types of the arguments while treating all ambiguous functions as if they were of type <hask>a -> b</hask>.
 
# The inferred type of the name's argument. The compiler will attempt to infer the types of the arguments while treating all ambiguous functions as if they were of type <hask>a -> b</hask>.
   
== Other Considerations ==
+
= Other Considerations =
   
 
It is possible to enrich the disambiguation with other sources of type information, such as the inferred return type, by considering the set of candidate definitions when attempting to infer the type of the argument, or by attempting to disambiguate all ambiguous names simultaneously to find a mutually type-checking set.
 
It is possible to enrich the disambiguation with other sources of type information, such as the inferred return type, by considering the set of candidate definitions when attempting to infer the type of the argument, or by attempting to disambiguate all ambiguous names simultaneously to find a mutually type-checking set.
Line 19: Line 17:
 
However, these would greatly complicate the implementation, and the above definition is sufficient to cover all of the regular use cases.
 
However, these would greatly complicate the implementation, and the above definition is sufficient to cover all of the regular use cases.
   
== Example ==
+
= Example =
   
 
Adapted from [http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution TDNR]:
 
Adapted from [http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution TDNR]:
Line 36: Line 34:
 
The compiler will determine that <hask>b</hask> is of type <hask>Button</hask> from <hask>f</hask>'s signature, and the first <hask>reset</hask> must therefore be <hask>Button.reset</hask>, as this is the only one which applies to <hask>Buttons</hask>. Similarly <hask>c</hask> is a <hask>Canvas</hask>, and it's <hask>reset</hask> must therefore be <hask>Canvas.reset</hask>.
 
The compiler will determine that <hask>b</hask> is of type <hask>Button</hask> from <hask>f</hask>'s signature, and the first <hask>reset</hask> must therefore be <hask>Button.reset</hask>, as this is the only one which applies to <hask>Buttons</hask>. Similarly <hask>c</hask> is a <hask>Canvas</hask>, and it's <hask>reset</hask> must therefore be <hask>Canvas.reset</hask>.
   
== Backwards Compatibility ==
+
= Backwards Compatibility =
   
 
Activating this extension would have no effect on existing programs. It will only permit programs which previously failed to compile due to ambiguous names.
 
Activating this extension would have no effect on existing programs. It will only permit programs which previously failed to compile due to ambiguous names.
   
== Comparison to Overloaded Record Fields ==
+
= Comparison to Overloaded Record Fields =
   
 
[https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/MagicClasses Magic Type Classes], a component of [https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields Overloaded Record Fields], allow duplicate record names to be disambiguated. While there is some overlap, there are also some important differences, as they are solving different problems:
 
[https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/MagicClasses Magic Type Classes], a component of [https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields Overloaded Record Fields], allow duplicate record names to be disambiguated. While there is some overlap, there are also some important differences, as they are solving different problems:

Revision as of 08:27, 1 June 2016

The original TDNR proposal was fairly controversial, with almost all of the objections related to the new dot syntax. However, TDNR can be implemented without any changes to the syntax of Haskell and without adding any new operators.

Disambiguation

When GHC encounters an ambiguous name (i.e. imported from different modules without qualification), it will create a constraint for the name's type from available type information. If exactly one candidate definition matches this type constraint, it will be selected.

The following sources of type information will be used, in order:

  1. A type signature applied to the name.
  2. A type signature applied to the name's argument (if the name is a function).
  3. The inferred type of the name's argument. The compiler will attempt to infer the types of the arguments while treating all ambiguous functions as if they were of type a -> b.

Other Considerations

It is possible to enrich the disambiguation with other sources of type information, such as the inferred return type, by considering the set of candidate definitions when attempting to infer the type of the argument, or by attempting to disambiguate all ambiguous names simultaneously to find a mutually type-checking set.

However, these would greatly complicate the implementation, and the above definition is sufficient to cover all of the regular use cases.

Example

Adapted from TDNR:

{-# LANGUAGE TDNR #-}

module Foo where
  import Button( Button, reset )
  import Canvas( Canvas, reset )

  f :: Button -> Canvas -> IO ()
  f b c = do { reset b; reset c }

The compiler will determine that b is of type Button from f's signature, and the first reset must therefore be Button.reset, as this is the only one which applies to Buttons. Similarly c is a Canvas, and it's reset must therefore be Canvas.reset.

Backwards Compatibility

Activating this extension would have no effect on existing programs. It will only permit programs which previously failed to compile due to ambiguous names.

Comparison to Overloaded Record Fields

Magic Type Classes, a component of Overloaded Record Fields, allow duplicate record names to be disambiguated. While there is some overlap, there are also some important differences, as they are solving different problems:

  • ORF allows polymorphism and duplicate definitions in the same module, but only works for record selectors.
  • TDNR only allows the compiler to qualify bear names, makes no changes to the type system, and applies to all names.