Skip to content

Instantly share code, notes, and snippets.

@Lucus16
Created February 15, 2024 17:18
Show Gist options
  • Select an option

  • Save Lucus16/167841bc859ca33e17100f56ff851468 to your computer and use it in GitHub Desktop.

Select an option

Save Lucus16/167841bc859ca33e17100f56ff851468 to your computer and use it in GitHub Desktop.
Haskell supports lifetimes!
Diagnostics:
• Couldn't match type ‘b0’ with ‘Handle h’
Expected: (Text, b0)
Actual: (Text, Handle h)
• because type variable ‘h’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall h. Handle h -> IO (Text, b0)
at /home/lars/h/src/Lifetime.hs:(22,44)-(24,18)
• In the first argument of ‘pure’, namely ‘(line, h)’
In a stmt of a 'do' block: pure (line, h)
In the expression:
do line <- hGetLine h
pure (line, h)
• Relevant bindings include
h :: Handle h (bound at /home/lars/h/src/Lifetime.hs:22:45) [-Wdeferred-type-errors]
{-# LANGUAGE RankNTypes #-}
module Lifetime where
import Data.Text (Text)
import Data.Text.IO qualified as Text
import System.IO (IOMode (..))
import System.IO qualified as Base
import Prelude hiding (Handle, withFile)
import Prelude qualified as Base
newtype Handle h = Handle {unHandle :: Base.Handle}
withFile :: FilePath -> IOMode -> (forall h. Handle h -> IO r) -> IO r
withFile path mode f = Base.withFile path mode (f . Handle)
hGetLine :: Handle h -> IO Text
hGetLine (Handle h) = Text.hGetLine h
main :: IO ()
main = do
(line, h) <- withFile "h.cabal" ReadMode \h -> do
line <- hGetLine h
pure (line, h)
pure ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment