{-# LANGUAGE LinearTypes #-} module LinearLet where import GHC.Types f :: a -> a f x = let %1 y = x in y f' :: a %1 -> a f' x = let %1 y = x in y f'' :: a %1 -> a f'' x = let y = x in y g :: a -> (a, a, a) g x = let %'Many y = x in (x, x, x) h :: a %1 -> a h x = y where %1 y = x h' :: a %1 -> a h' x = y where y = x i :: Maybe a %1 -> a i x = let %1 !(Just y) = x in y j :: (a, b) %1 -> (b, a) j x = let !(y, z) = x in (z, y) -- The non-variable pattern let binding cannot be linear because it's inferred as -- polymorphic. See Note [Non-variable pattern bindings aren't linear] in GHC.Tc.Gen.Bind -- -- The local let binding is inferred as polymorphic despite MonoLocalBinds -- because it is closed. This behaviour is not very problematic (this will never -- need to be linear), but can be a little surprising. k :: a -> (a, Bool) k x = let !(f, b) = ((\y -> y), b) in (f x, b) -- let !y = (without a multiplicity annotation) uses the same code path as let y = -- (FunBind) not that of pattern bindings (PatBind). The desugaring of a strict -- pattern involves `seq`, with which we need to be careful when dealing with -- linear types. l :: a %1 -> a l x = let !y = x in y