or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ast.mdbuild.mdcli.mdcodegen.mdcorefn.mddocs.mderrors.mdide.mdindex.mdinteractive.mdparser.mdsugar.mdtypes.md
tile.json

sugar.mddocs/

Desugaring Pipeline (Sugar)

The Sugar modules implement the desugaring pipeline that transforms high-level PureScript syntax into simpler, more explicit forms. This pipeline runs after parsing but before type checking, eliminating syntactic conveniences and expanding them into their underlying representations.

Capabilities

Main Desugaring Pipeline

The complete desugaring transformation that processes modules through all desugaring passes in the correct order.

-- | Main desugaring function that applies all passes
desugar :: [ExternsFile] -> Module -> StateT (Env, UsedImports) (SupplyT (Either MultipleErrors)) Module

-- | The complete desugaring pipeline includes:
-- 1. Remove signed literals (replace with negate applications)
-- 2. Desugar object wildcards into lambdas  
-- 3. Desugar operator sections
-- 4. Desugar do-notation into bind applications
-- 5. Desugar ado-notation into apply applications
-- 6. Desugar case declarations into case expressions
-- 7. Desugar type declarations into type annotations
-- 8. Qualify unqualified names and types
-- 9. Rebracket user-defined operators
-- 10. Introduce type class dictionaries and instances
-- 11. Create binding groups for mutually recursive definitions

Do Notation Desugaring

Transforms do-notation blocks into explicit bind and discard applications using the Monad type class.

-- | Desugar do-notation in a module
desugarDoModule :: Module -> m Module

-- | Do notation elements before desugaring
data DoNotationElement
  = DoNotationValue Expr                                 -- Pure expression 
  | DoNotationBind Binder Expr                          -- Monadic bind
  | DoNotationLet [Declaration]                         -- Let binding
  | PositionedDoNotationElement SourcePos [Comment] DoNotationElement

-- | Transform do-notation to bind applications
-- do { x <- m; f x } becomes m >>= \x -> f x
-- do { m; n } becomes m >> n  
-- do { let x = y; m } becomes let x = y in m
desugarDoStatement :: DoNotationElement -> Expr -> m Expr

Ado Notation Desugaring

Transforms ado-notation blocks into explicit apply applications using the Apply type class for applicative computations.

-- | Desugar ado-notation in a module
desugarAdoModule :: Module -> m Module

-- | Transform ado-notation to apply applications
-- ado { x <- m1; y <- m2; in f x y } becomes lift2 f m1 m2
-- ado { x <- m1; let y = g x; in f x y } becomes m1 <#> \x -> let y = g x in f x y
desugarAdoStatement :: [DoNotationElement] -> Expr -> m Expr

Operator Desugaring

Handles operator precedence, associativity, and sections (partial application of operators).

-- | Rebracket operators according to precedence and associativity
rebracketOperators :: Module -> m Module

-- | Desugar operator sections into lambda expressions  
desugarOperatorSections :: Module -> m Module

-- | Operator fixity information
data Fixity = Fixity Associativity Precedence

data Associativity = Infixl | Infixr | Infix

type Precedence = Integer

-- | Transform operator sections:
-- (+ 1) becomes \x -> x + 1
-- (1 +) becomes \x -> 1 + x  
-- (+) becomes \x y -> x + y
desugarOperatorSection :: Expr -> m Expr

Type Class Desugaring

Transforms type class instances into dictionary types and replaces constrained types with dictionary parameters.

-- | Desugar type classes and instances
desugarTypeClasses :: [ExternsFile] -> Module -> m Module

-- | Transform type class into newtype dictionary
-- class Show a where show :: a -> String
-- becomes: newtype Show a = Show { show :: a -> String }
desugarTypeClass :: Declaration -> m [Declaration]

-- | Transform instance into dictionary value
-- instance showInt :: Show Int where show = showIntImpl  
-- becomes: showInt :: Show Int; showInt = Show { show: showIntImpl }
desugarInstance :: Declaration -> m [Declaration]

-- | Replace constrained types with dictionary parameters
-- f :: Show a => a -> String becomes f :: Show a -> a -> String
desugarConstrainedType :: Type -> m Type

Deriving Desugaring

Automatically generates type class instances for data types using deriving clauses.

-- | Generate derived instances for data types
deriveInstances :: Module -> m Module

-- | Derivable type classes
data DeriveClass
  = Eq        -- Structural equality
  | Ord       -- Structural ordering  
  | Functor   -- Functor mapping
  | Generic   -- Generic representation
  | Newtype   -- Newtype wrapping/unwrapping

-- | Generate instance for a derivable class
deriveInstance :: DeriveClass -> DataDeclaration -> m Declaration

Object Wildcard Desugaring

Transforms object patterns with wildcards into explicit lambda expressions.

-- | Desugar object wildcards
desugarObjectWildcards :: Module -> m Module

-- | Transform record wildcards:
-- { x, y, .. } becomes \r -> { x: r.x, y: r.y, z: r.z, ... }
-- where .. represents all other fields in scope
desugarObjectWildcard :: Expr -> m Expr

Case Declaration Desugaring

Converts top-level pattern matching function definitions into explicit case expressions.

-- | Desugar case declarations  
desugarCaseDeclarations :: Module -> m Module

-- | Transform pattern matching function definitions:
-- f true  = 1
-- f false = 2  
-- becomes: f = \x -> case x of { true -> 1; false -> 2 }
desugarCaseDeclaration :: [Declaration] -> m Declaration

Name Resolution and Qualification

Resolves unqualified names by looking them up in the current scope and qualifying them appropriately.

-- | Qualify all names in a module
qualifyNames :: Module -> m Module

-- | Resolve and qualify a name
qualifyName :: Ident -> m (Qualified Ident)

-- | Resolve and qualify a type name  
qualifyTypeName :: ProperName 'TypeName -> m (Qualified (ProperName 'TypeName))

-- | Name resolution environment
data Env = Env
  { envModuleName :: ModuleName                          -- Current module
  , envImports :: ImportedModules                        -- Available imports
  , envTypeClassDictionaries :: Map (Qualified Ident) TypeClassDictionaryInScope
  , envNameKinds :: Map (Qualified Ident) (Type (), NameKind)
  }

Binding Group Creation

Analyzes dependencies between declarations and creates mutually recursive binding groups.

-- | Create binding groups for mutually recursive definitions
createBindingGroups :: Module -> m Module

-- | A binding group of mutually recursive declarations
data BindingGroup = BindingGroup
  { bindingGroupDeclarations :: [Declaration]            -- Group members
  , bindingGroupDependencies :: [Ident]                 -- External dependencies
  }

-- | Analyze dependencies between declarations
analyzeDependencies :: [Declaration] -> DependencyGraph

-- | Strongly connected components for mutual recursion
createSCCs :: DependencyGraph -> [BindingGroup]

Let Pattern Desugaring

Transforms pattern matches in let bindings into case expressions.

-- | Desugar let patterns
desugarLetPatterns :: Module -> m Module

-- | Transform let pattern bindings:
-- let { x, y } = record in expr
-- becomes: case record of { x, y } -> expr
desugarLetPattern :: Declaration -> m Declaration

Type Declaration Desugaring

Converts separate type signatures into inline type annotations on value declarations.

-- | Desugar type declarations
desugarTypeDeclarations :: Module -> m Module

-- | Attach type annotations to value declarations
-- f :: Int -> Int; f x = x + 1  
-- becomes: f :: Int -> Int; f = (\x -> x + 1) :: Int -> Int
attachTypeAnnotation :: Declaration -> Declaration -> m Declaration

Usage Examples

Basic Desugaring Pipeline

import Language.PureScript.Sugar

-- Desugar a complete module
desugarModule :: [ExternsFile] -> Module -> Either MultipleErrors Module
desugarModule externs modul = 
  evalSupply 0 $ runExceptT $ evalStateT (desugar externs modul) (emptyEnv, mempty)

-- Desugar just do-notation
desugarDoOnly :: Module -> Either MultipleErrors Module  
desugarDoOnly modul = 
  evalSupply 0 $ runExceptT $ desugarDoModule modul

Do Notation Transformation

-- Input do-notation:
-- do
--   x <- action1
--   y <- action2 x  
--   pure (x + y)

-- Output after desugaring:
-- action1 >>= \x ->
--   action2 x >>= \y ->  
--     pure (x + y)

Ado Notation Transformation

-- Input ado-notation:
-- ado  
--   x <- action1
--   y <- action2
--   in f x y

-- Output after desugaring:  
-- lift2 f action1 action2

Type Class Desugaring

-- Input type class:
-- class Show a where
--   show :: a -> String

-- Output after desugaring:
-- newtype Show a = Show { show :: a -> String }

-- Input instance:  
-- instance showInt :: Show Int where
--   show = showIntImpl

-- Output after desugaring:
-- showInt :: Show Int  
-- showInt = Show { show: showIntImpl }

Operator Section Desugaring

-- Input operator sections:
map (+ 1) [1, 2, 3]     -- Becomes: map (\x -> x + 1) [1, 2, 3]
map (1 +) [1, 2, 3]     -- Becomes: map (\x -> 1 + x) [1, 2, 3]  
map (+) pairs           -- Becomes: map (\x y -> x + y) pairs

Custom Desugaring Pass

-- Create a custom desugaring transformation
customDesugar :: Module -> Either MultipleErrors Module
customDesugar modul = do
  -- Apply individual passes in order
  step1 <- desugarObjectWildcards modul
  step2 <- desugarDoModule step1  
  step3 <- desugarAdoModule step2
  step4 <- rebracketOperators step3
  desugarTypeClasses [] step4