Partial Type Signatures Thomas Winant Dominique Devriese Frank - - PowerPoint PPT Presentation
Partial Type Signatures Thomas Winant Dominique Devriese Frank - - PowerPoint PPT Presentation
HIW14 September 6th 2014 Partial Type Signatures Thomas Winant Dominique Devriese Frank Piessens Tom Schrijvers 2 / 29 PARTIAL TYPE SIGNATURE 3 / 29 PARTIAL TYPE SIGNATURE 3 / 29 foo file = do ... ? ... PARTIAL TYPE SIGNATURE 3
Dominique Devriese Frank Piessens Tom Schrijvers
2 / 29
PARTIAL TYPE SIGNATURE
3 / 29
PARTIAL TYPE SIGNATURE
foo file = do ... ? ...
3 / 29
PARTIAL TYPE SIGNATURE
foo file = do ... ...
3 / 29
PARTIAL TYPE SIGNATURE
foo file = do ... ...
Found hole ‘_’ with type: … Relevant bindings include …
3 / 29
PARTIAL TYPE SIGNATURE
foo file = do ...
Found hole ‘_’ with type: … Relevant bindings include …
3 / 29
PARTIAL TYPE SIGNATURE
foo :: FilePath → IO ? foo file = do ...
Found hole ‘_’ with type: … Relevant bindings include …
3 / 29
PARTIAL TYPE SIGNATURE
foo :: FilePath → IO foo file = do ...
Found hole ‘_’ with type: … Relevant bindings include …
3 / 29
PARTIAL TYPE SIGNATURE
foo :: FilePath → IO foo file = do ...
Found hole ‘_’ with type: … In the type signature: foo :: FilePath -> IO _ To use the inferred type, enable PartialTypeSignatures
3 / 29
OVERVIEW
Motivation Syntax Formalisation Implementation
4 / 29
MOTIVATION
5 / 29
MOTIVATION
Dilemma: write the complete type signature or none at all? Compromise: partial type signatures Mix annotated with inferred types using wildcards ( ). foo Bool
- - Inferred: Bool
Bool Bool foo x = x x Combine type checking with type inference.
6 / 29
MOTIVATION
Dilemma: write the complete type signature or none at all? Compromise: partial type signatures Mix annotated with inferred types using wildcards ( ). foo Bool
- - Inferred: Bool
Bool Bool foo x = x x Combine type checking with type inference.
6 / 29
MOTIVATION
Dilemma: write the complete type signature or none at all? Compromise: partial type signatures ⇒ Mix annotated with inferred types using wildcards ( ). foo :: → ( , Bool)
- - Inferred: Bool → (Bool, Bool)
foo x = (x, x) Combine type checking with type inference.
6 / 29
MOTIVATION
Dilemma: write the complete type signature or none at all? Compromise: partial type signatures ⇒ Mix annotated with inferred types using wildcards ( ). foo :: → ( , Bool)
- - Inferred: Bool → (Bool, Bool)
foo x = (x, x) ⇒ Combine type checking with type inference.
6 / 29
MOTIVATION
During development: Functions & types change frequently Type signatures need to be updated Type signatures are omitted Documentation & type checking against signature lost Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently
Type signatures need to be updated Type signatures are omitted Documentation & type checking against signature lost Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently ▶ Type signatures need to be updated
Type signatures are omitted Documentation & type checking against signature lost Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently ▶ Type signatures need to be updated ▶ Type signatures are omitted
Documentation & type checking against signature lost Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently ▶ Type signatures need to be updated ▶ Type signatures are omitted ▶ Documentation & type checking against signature lost
Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently ▶ Type signatures need to be updated ▶ Type signatures are omitted ▶ Documentation & type checking against signature lost
⇒ Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
During development:
▶ Functions & types change frequently ▶ Type signatures need to be updated ▶ Type signatures are omitted ▶ Documentation & type checking against signature lost
⇒ Partial type signatures Annotate the fixed parts of the type and replace the variable parts with wildcards.
7 / 29
MOTIVATION
The complete type is not yet known. Agda-style hole-driven development bar f x y = f x y
8 / 29
MOTIVATION
The complete type is not yet known. Agda-style hole-driven development bar f x y = f x y
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar f x y = f x y
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: → (Char, Int) → bar f (x, y) = ¬ ( f x y)
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: → (Char, Int) → bar f (x, y) = ¬ ( f x y)
Found hole ‘_’ with type: Char -> Int -> Bool In the type signature: bar :: _ -> (Char, Int) -> _ ...
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: (Char → Int → Bool) → (Char, Int) → bar f (x, y) = ¬ ( f x y)
Found hole ‘_’ with type: Char -> Int -> Bool In the type signature: bar :: _ -> (Char, Int) -> _ ...
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: (Char → Int → Bool) → (Char, Int) → bar f (x, y) = ¬ ( f x y)
Found hole ‘_’ with type: Bool In the type signature: bar :: _ -> (Char, Int) -> _ ...
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: (Char → Int → Bool) → (Char, Int) → Bool bar f (x, y) = ¬ ( f x y)
Found hole ‘_’ with type: Bool In the type signature: bar :: _ -> (Char, Int) -> _ ...
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development bar :: (Char → Int → Bool) → (Char, Int) → Bool bar f (x, y) = ¬ ( f x y) Emacs support for TypedHoles thanks to Alejandro Serrano Mena’s GSoC project. Relatively easy to add support for PartialTypeSignatures.
8 / 29
MOTIVATION
The complete type is not yet known. ⇒ Agda-style hole-driven development {-# LANGUAGE PartialTypeSignatures #-} bar :: → (Char, Int) → bar f (x, y) = ¬ ( f x y) No need to fill them in!
8 / 29
MOTIVATION
replaceLoopsRuleP :: (ProductionRule p, EpsProductionRule p, RecProductionRule p phi r, TokenProductionRule p t, PenaltyProductionRule p) ⇒ PenaltyExtendedContextFreeRule phi r t v → (∀ix.phi ix → p [r ix]) → (∀ix.phi ix → p [r ix]) → p v Distinguish important type information from distracting type information replaceLoopsRuleP PenaltyExtendedContextFreeRule phi r t v ix phi ix p r ix ix phi ix p r ix p v
9 / 29
MOTIVATION
replaceLoopsRuleP :: (ProductionRule p, EpsProductionRule p, RecProductionRule p phi r, TokenProductionRule p t, PenaltyProductionRule p) ⇒ PenaltyExtendedContextFreeRule phi r t v → (∀ix.phi ix → p [r ix]) → (∀ix.phi ix → p [r ix]) → p v Distinguish important type information from distracting type information replaceLoopsRuleP PenaltyExtendedContextFreeRule phi r t v ix phi ix p r ix ix phi ix p r ix p v
9 / 29
MOTIVATION
replaceLoopsRuleP :: (ProductionRule p, EpsProductionRule p, RecProductionRule p phi r, TokenProductionRule p t, PenaltyProductionRule p) ⇒ PenaltyExtendedContextFreeRule phi r t v → (∀ix.phi ix → p [r ix]) → (∀ix.phi ix → p [r ix]) → p v Distinguish important type information from distracting type information replaceLoopsRuleP :: ⇒ PenaltyExtendedContextFreeRule phi r t v → (∀ix.phi ix → p [r ix]) → (∀ix.phi ix → p [r ix]) → p v
9 / 29
MOTIVATION
Noninferable types, e.g. higher-rank types: foo x = (x [True, False], x [’a’, ’b’]) test = foo reverse
- - reverse :: ∀a.[a] → [a]
10 / 29
MOTIVATION
Noninferable types, e.g. higher-rank types: foo :: (∀a.[a] → [a]) → ([Bool], [Char]) foo x = (x [True, False], x [’a’, ’b’]) test = foo reverse
- - reverse :: ∀a.[a] → [a]
10 / 29
MOTIVATION
Noninferable types, e.g. higher-rank types: foo :: (∀a.[a] → [a]) → foo x = (x [True, False], x [’a’, ’b’]) test = foo reverse
- - reverse :: ∀a.[a] → [a]
10 / 29
SYNTAX
11 / 29
TYPE WILDCARDS
SYNTAX
filter :: (a → Bool) → [a] → [a] filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: (a → ) → [a] → [a]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: ( → Bool) → [a] → [a]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: → [a] → [a]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: → [a] → [ ]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: → [a] →
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: → →
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter :: →
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter ::
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
TYPE WILDCARDS
SYNTAX
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
12 / 29
NAMED WILDCARDS
SYNTAX
filter = filter pred x xs pred x = x filter pred xs
- therwise =
filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
filter :: (a → Bool) → [a] → [a] filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
filter :: ( x → x) → [ x] → [ x]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
Inferred: (Bool → Bool) → [Bool] → [Bool] filter :: ( x → x) → [ x] → [ x]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
filter :: ( x → Bool) → [ x] → [ x]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
Inferred: (w_x → Bool) → [w_x] → [w_x] filter :: ( x → Bool) → [ x] → [ x]
filter [ ] = [ ] filter pred (x : xs) | pred x = x : filter pred xs | otherwise = filter pred xs
13 / 29
NAMED WILDCARDS
SYNTAX
eq :: Eq a ⇒ a → a → Bool eq x y = x ≡ y
14 / 29
NAMED WILDCARDS
SYNTAX
eq :: Eq x ⇒ x → x → Bool
eq x y = x ≡ y
14 / 29
NAMED WILDCARDS
SYNTAX
Inferred: Eq w_x ⇒ w_x → w_x → Bool eq :: Eq x ⇒ x → x → Bool
eq x y = x ≡ y
14 / 29
NAMED WILDCARDS
SYNTAX
eq :: Eq x ⇒ x → x → x
eq x y = x ≡ y
14 / 29
NAMED WILDCARDS
SYNTAX
Inferred: Eq Bool ⇒ Bool → Bool → Bool eq :: Eq x ⇒ x → x → x
eq x y = x ≡ y
14 / 29
NAMED WILDCARDS
SYNTAX
Inferred: Bool → Bool → Bool eq :: Eq x ⇒ x → x → x
eq x y = x ≡ y
14 / 29
CONSTRAINT WILDCARDS
SYNTAX
15 / 29
CONSTRAINT WILDCARDS
SYNTAX
bar :: Ord a ⇒ a → a → Bool bar x y = x ≡ y
- - class Eq a => Ord x
15 / 29
CONSTRAINT WILDCARDS
SYNTAX
bar :: Ord ⇒ a → a → Bool
bar x y = x ≡ y
- - class Eq a => Ord x
15 / 29
CONSTRAINT WILDCARDS
SYNTAX
Mismatch: inferred Eq a vs. annotated Ord bar :: Ord ⇒ a → a → Bool
bar x y = x ≡ y
- - class Eq a => Ord x
15 / 29
CONSTRAINT WILDCARDS
SYNTAX
16 / 29
CONSTRAINT WILDCARDS
SYNTAX
foo :: (Show a, Num a) ⇒ a → String foo x = show (x + 1)
16 / 29
CONSTRAINT WILDCARDS
SYNTAX
foo :: a ⇒ a → String
foo x = show (x + 1)
16 / 29
CONSTRAINT WILDCARDS
SYNTAX
Infer? Show a ⇒ a → String foo :: a ⇒ a → String
foo x = show (x + 1)
16 / 29
CONSTRAINT WILDCARDS
SYNTAX
Infer? Num a ⇒ a → String foo :: a ⇒ a → String
foo x = show (x + 1)
16 / 29
CONSTRAINT WILDCARDS
SYNTAX
Compromise
▶ Only named wildcards in constraints… ▶ …when present in the rest of the type
Eq a a Bool No Eq x a a Bool No Eq x x x Bool Yes
17 / 29
CONSTRAINT WILDCARDS
SYNTAX
Compromise
▶ Only named wildcards in constraints… ▶ …when present in the rest of the type
Eq ⇒ a → a → Bool No Eq x a a Bool No Eq x x x Bool Yes
17 / 29
CONSTRAINT WILDCARDS
SYNTAX
Compromise
▶ Only named wildcards in constraints… ▶ …when present in the rest of the type
Eq ⇒ a → a → Bool No Eq x ⇒ a → a → Bool No Eq x x x Bool Yes
17 / 29
CONSTRAINT WILDCARDS
SYNTAX
Compromise
▶ Only named wildcards in constraints… ▶ …when present in the rest of the type
Eq ⇒ a → a → Bool No Eq x ⇒ a → a → Bool No Eq x ⇒ x → x → Bool Yes
17 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
foo :: (Show a, Num a) ⇒ a → String foo x = show (x + 1)
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
foo :: ⇒ a → String
foo x = show (x + 1)
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: (Show a, Num a) foo :: ⇒ a → String
foo x = show (x + 1)
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
foo :: (Num a, ) ⇒ a → String
foo x = show (x + 1)
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a foo :: (Num a, ) ⇒ a → String
foo x = show (x + 1)
18 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
bar :: Show a ⇒ a → a bar x = show x
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
bar :: ⇒ a → a
bar x = show x
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a Inferred: Show a ⇒ a → a bar :: ⇒ a → a
bar x = show x
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
bar :: (Num a, ) ⇒ a → a
bar x = show x
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a Inferred: (Num a, Show a) ⇒ a → a bar :: (Num a, ) ⇒ a → a
bar x = show x
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a Inferred: (Num a, Show a) ⇒ a → a bar :: (Num a, ) ⇒ a → a
bar x = show x Proposed simplification: ignore annotated constraints
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a Inferred: (✘✘✘✘
✘
Num a, Show a) ⇒ a → a bar :: (Num a, ) ⇒ a → a
bar x = show x Proposed simplification: ignore annotated constraints
19 / 29
EXTRA-CONSTRAINTS WILDCARD
SYNTAX
Inferred constraints: Show a Inferred: Show a ⇒ a → a bar :: (Num a, ) ⇒ a → a
bar x = show x Proposed simplification: ignore annotated constraints
19 / 29
FORMALISATION
Partial Type Signatures for Haskell. Thomas Winant, Dominique Devriese, Frank Piessens, Tom Schrijvers. In Practical Aspects of Declarative Languages 2014 (PADL’14)
20 / 29
IDEA
FORMALISATION
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg x = x
21 / 29
IDEA
FORMALISATION
secondArg x = x
21 / 29
IDEA
FORMALISATION
secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
21 / 29
IDEA
FORMALISATION
secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
21 / 29
IDEA
FORMALISATION
secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β]
21 / 29
IDEA
FORMALISATION
secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β
21 / 29
IDEA
FORMALISATION
secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β ⇒ Generalise: secondArg :: ∀a b.a → b → b
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β ⇒ Generalise: secondArg :: ∀a b.a → b → b
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β ⇒ Generalise: secondArg :: ∀a b.a → b → b Idea: replace wildcards with unification variables
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ)
Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β ⇒ Generalise: secondArg :: ∀a b.a → b → b Idea: replace wildcards with unification variables Wildcard desugaring relation: ( → → Bool) ➾ (ω1 → ω2 → Bool)
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ, (ω1 → ω2 → Bool) ∼ (α → β → γ))
- Constraints
Solve the constraints: [γ → β] ⇒ secondArg :: α → β → β ⇒ Generalise: secondArg :: ∀a b.a → b → b Idea: replace wildcards with unification variables Wildcard desugaring relation: ( → → Bool) ➾ (ω1 → ω2 → Bool)
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ, (ω1 → ω2 → Bool) ∼ (α → β → γ))
- Constraints
Solve the constraints: [γ → Bool, β → Bool, ω2 → Bool, α → ω1] Idea: replace wildcards with unification variables Wildcard desugaring relation: ( → → Bool) ➾ (ω1 → ω2 → Bool)
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ, (ω1 → ω2 → Bool) ∼ (α → β → γ))
- Constraints
Solve the constraints: [γ → Bool, β → Bool, ω2 → Bool, α → ω1] ⇒ secondArg :: ω1 → Bool → Bool Idea: replace wildcards with unification variables Wildcard desugaring relation: ( → → Bool) ➾ (ω1 → ω2 → Bool)
21 / 29
IDEA
FORMALISATION
secondArg :: → → Bool secondArg
α
x
- β
=
β
- x
- γ
:
type
- α → β → γ
⇝ (β ∼ γ, (ω1 → ω2 → Bool) ∼ (α → β → γ))
- Constraints
Solve the constraints: [γ → Bool, β → Bool, ω2 → Bool, α → ω1] ⇒ secondArg :: ω1 → Bool → Bool ⇒ Generalise: secondArg :: ∀a.a → Bool → Bool Idea: replace wildcards with unification variables Wildcard desugaring relation: ( → → Bool) ➾ (ω1 → ω2 → Bool)
21 / 29
PROOFS
FORMALISATION
Theorem 1: Conservative extension For functions with non-partial type signatures, ghc infers the same types as before. Theorem 2: Generalisation of type inference f = e is equivalent with f = e. Theorem 3: Algorithm soundness
22 / 29
PROOFS
FORMALISATION
Theorem 1: Conservative extension For functions with non-partial type signatures, ghc infers the same types as before. Theorem 2: Generalisation of type inference f :: ⇒ = e is equivalent with f = e. Theorem 3: Algorithm soundness
22 / 29
PROOFS
FORMALISATION
Theorem 1: Conservative extension For functions with non-partial type signatures, ghc infers the same types as before. Theorem 2: Generalisation of type inference f :: ⇒ = e is equivalent with f = e. Theorem 3: Algorithm soundness
22 / 29
IMPLEMENTATION
23 / 29
IMPLEMENTATION
▶ Parser support for wildcards
Named wildcard syntax clashes with type variable syntax: foo a a foo x = x
24 / 29
IMPLEMENTATION
▶ Parser support for wildcards ▶ Named wildcard syntax clashes with type variable syntax:
foo :: a → a foo x = ¬ x
24 / 29
IMPLEMENTATION
▶ Parser support for wildcards ▶ Named wildcard syntax clashes with type variable syntax:
foo :: a → a foo x = ¬ x
Couldn’t match expected type ‘_a’ with actual type ‘Bool’ ‘_a’ is a rigid type variable bound by ...
24 / 29
IMPLEMENTATION
▶ Parser support for wildcards ▶ Named wildcard syntax clashes with type variable syntax:
{-# LANGUAGE NamedWildcards #-} foo :: a → a foo x = ¬ x
Couldn’t match expected type ‘_a’ with actual type ‘Bool’ ‘_a’ is a rigid type variable bound by ...
backwards compatible unless the NamedWildcards extension is enabled.
24 / 29
IMPLEMENTATION
▶ Parser support for wildcards ▶ Named wildcard syntax clashes with type variable syntax:
{-# LANGUAGE NamedWildcards #-} foo :: a → a foo x = ¬ x
Found hole ‘_’ with type: Bool In the type signature: foo :: _a -> _a
backwards compatible unless the NamedWildcards extension is enabled.
24 / 29
IMPLEMENTATION
▶ Disallow wildcards in particular types:
class Show a where show :: a → instance Show where ... data Foo = {bar :: Maybe } ...
25 / 29
IMPLEMENTATION
▶ Quantify desugared wildcards per TypeSig, imitating the
scoping behaviour of ScopedTypeVariables. {-# LANGUAGE NamedWildcards #-} foo a Char foo x = let v = x g a a g y = y in g ’z’
26 / 29
IMPLEMENTATION
▶ Quantify desugared wildcards per TypeSig, imitating the
scoping behaviour of ScopedTypeVariables. {-# LANGUAGE NamedWildcards #-} foo :: a → Char foo x = let v = ¬ x g :: a → a g y = y in (g ’z’)
26 / 29
IMPLEMENTATION
▶ Quantify desugared wildcards per TypeSig, imitating the
scoping behaviour of ScopedTypeVariables. {-# LANGUAGE NamedWildcards, ScopedTypeVariables #-} foo :: a → Char foo x = let v = ¬ x g :: a → a g y = y in (g ’z’)
Couldn’t match expected type ‘Bool’ with actual type ‘Char’ In the first argument of ‘g’, namely ‘’z’’
26 / 29
IMPLEMENTATION
▶ Just like for TypedHoles, when type checking, we
generate an insoluble hole constraint between each wildcard unification variable and its inferred type. After solving the constraints, these hole constraints are left over, and are converted into error messages. They are not generated when PartialTypeSignatures is enabled.
27 / 29
IMPLEMENTATION
▶ Just like for TypedHoles, when type checking, we
generate an insoluble hole constraint between each wildcard unification variable and its inferred type.
▶ After solving the constraints, these hole constraints are
left over, and are converted into error messages. They are not generated when PartialTypeSignatures is enabled.
27 / 29
IMPLEMENTATION
▶ Just like for TypedHoles, when type checking, we
generate an insoluble hole constraint between each wildcard unification variable and its inferred type.
▶ After solving the constraints, these hole constraints are
left over, and are converted into error messages.
▶ They are not generated when PartialTypeSignatures
is enabled.
27 / 29
CODE
IMPLEMENTATION
Code
https://github.com/mrBliss/ghc
Phabricator
https://phabricator.haskell.org/D168
Trac Ticket #9478 Coming to GHC some time soon!
28 / 29
THANK YOU
Q & A
29 / 29