Wolfgang Jeltsch pushed to branch wip/jeltsch/text-read-implementation-into-base at Glasgow Haskell Compiler / GHC
Commits:
-
17eef35d
by Wolfgang Jeltsch at 2026-05-04T15:38:57+03:00
10 changed files:
- libraries/base/src/Data/Functor/Classes.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/Text/Read.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
- − libraries/ghc-internal/src/GHC/Internal/Text/Read.hs
- testsuite/tests/th/T24111.stdout
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
Changes:
| ... | ... | @@ -85,7 +85,7 @@ import GHC.Internal.Read (expectP, list, paren, readField) |
| 85 | 85 | import GHC.Internal.Show (appPrec)
|
| 86 | 86 | |
| 87 | 87 | import GHC.Internal.Text.ParserCombinators.ReadPrec (ReadPrec, readPrec_to_S, readS_to_Prec, pfail)
|
| 88 | -import GHC.Internal.Text.Read (Read(..), parens, prec, step, reset)
|
|
| 88 | +import Text.Read (Read(..), parens, prec, step, reset)
|
|
| 89 | 89 | import GHC.Internal.Text.Read.Lex (Lexeme(..))
|
| 90 | 90 | import GHC.Internal.Text.Show (showListWith)
|
| 91 | 91 | import Prelude
|
| ... | ... | @@ -35,7 +35,7 @@ import GHC.Internal.Data.Foldable (Foldable(..)) |
| 35 | 35 | import GHC.Internal.Data.Monoid (Sum(..), All(..), Any(..), Product(..))
|
| 36 | 36 | import GHC.Internal.Data.Type.Equality (TestEquality(..), (:~:)(..))
|
| 37 | 37 | import GHC.Generics (Generic, Generic1)
|
| 38 | -import GHC.Internal.Text.Read (Read(..), ReadPrec, readListDefault, readListPrecDefault)
|
|
| 38 | +import Text.Read (Read(..), ReadPrec, readListDefault, readListPrecDefault)
|
|
| 39 | 39 | import Prelude
|
| 40 | 40 | |
| 41 | 41 | infixr 9 `Compose`
|
| ... | ... | @@ -179,7 +179,7 @@ import GHC.Internal.Data.Tuple |
| 179 | 179 | import GHC.Internal.Base hiding ( foldr, mapM, sequence )
|
| 180 | 180 | import GHC.Internal.Classes
|
| 181 | 181 | import GHC.Internal.Err
|
| 182 | -import GHC.Internal.Text.Read
|
|
| 182 | +import Text.Read
|
|
| 183 | 183 | import GHC.Internal.Enum
|
| 184 | 184 | import GHC.Internal.Num
|
| 185 | 185 | import GHC.Internal.Prim (seq)
|
| ... | ... | @@ -39,5 +39,84 @@ module Text.Read |
| 39 | 39 | readMaybe
|
| 40 | 40 | ) where
|
| 41 | 41 | |
| 42 | -import GHC.Internal.Text.Read
|
|
| 42 | +import GHC.Err (errorWithoutStackTrace)
|
|
| 43 | +import GHC.Read
|
|
| 44 | + (
|
|
| 45 | + ReadS,
|
|
| 46 | + Read (readsPrec, readList, readPrec, readListPrec),
|
|
| 47 | + lex,
|
|
| 48 | + readParen,
|
|
| 49 | + readListDefault,
|
|
| 50 | + lexP,
|
|
| 51 | + parens,
|
|
| 52 | + readListPrecDefault
|
|
| 53 | + )
|
|
| 54 | +import Control.Monad (return)
|
|
| 55 | +import Data.Function (id)
|
|
| 56 | +import Data.Maybe (Maybe (Nothing, Just))
|
|
| 57 | +import Data.Either (Either (Left, Right), either)
|
|
| 58 | +import Data.String (String)
|
|
| 59 | +import Text.Read.Lex (Lexeme (Char, String, Punc, Ident, Symbol, Number, EOF))
|
|
| 60 | +import Text.ParserCombinators.ReadP (skipSpaces)
|
|
| 43 | 61 | import Text.ParserCombinators.ReadPrec
|
| 62 | + |
|
| 63 | +-- $setup
|
|
| 64 | +-- >>> import Prelude
|
|
| 65 | + |
|
| 66 | +------------------------------------------------------------------------
|
|
| 67 | +-- utility functions
|
|
| 68 | + |
|
| 69 | +-- | equivalent to 'readsPrec' with a precedence of 0.
|
|
| 70 | +reads :: Read a => ReadS a
|
|
| 71 | +reads = readsPrec minPrec
|
|
| 72 | + |
|
| 73 | +-- | Parse a string using the 'Read' instance.
|
|
| 74 | +-- Succeeds if there is exactly one valid result.
|
|
| 75 | +-- A 'Left' value indicates a parse error.
|
|
| 76 | +--
|
|
| 77 | +-- >>> readEither "123" :: Either String Int
|
|
| 78 | +-- Right 123
|
|
| 79 | +--
|
|
| 80 | +-- >>> readEither "hello" :: Either String Int
|
|
| 81 | +-- Left "Prelude.read: no parse"
|
|
| 82 | +--
|
|
| 83 | +-- @since base-4.6.0.0
|
|
| 84 | +readEither :: Read a => String -> Either String a
|
|
| 85 | +readEither s =
|
|
| 86 | + case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
|
|
| 87 | + [x] -> Right x
|
|
| 88 | + [] -> Left "Prelude.read: no parse"
|
|
| 89 | + _ -> Left "Prelude.read: ambiguous parse"
|
|
| 90 | + where
|
|
| 91 | + read' =
|
|
| 92 | + do x <- readPrec
|
|
| 93 | + lift skipSpaces
|
|
| 94 | + return x
|
|
| 95 | + |
|
| 96 | +-- | Parse a string using the 'Read' instance.
|
|
| 97 | +-- Succeeds if there is exactly one valid result.
|
|
| 98 | +--
|
|
| 99 | +-- >>> readMaybe "123" :: Maybe Int
|
|
| 100 | +-- Just 123
|
|
| 101 | +--
|
|
| 102 | +-- >>> readMaybe "hello" :: Maybe Int
|
|
| 103 | +-- Nothing
|
|
| 104 | +--
|
|
| 105 | +-- @since base-4.6.0.0
|
|
| 106 | +readMaybe :: Read a => String -> Maybe a
|
|
| 107 | +readMaybe s = case readEither s of
|
|
| 108 | + Left _ -> Nothing
|
|
| 109 | + Right a -> Just a
|
|
| 110 | + |
|
| 111 | +-- | The 'read' function reads input from a string, which must be
|
|
| 112 | +-- completely consumed by the input process. 'read' fails with an 'error' if the
|
|
| 113 | +-- parse is unsuccessful, and it is therefore discouraged from being used in
|
|
| 114 | +-- real applications. Use 'readMaybe' or 'readEither' for safe alternatives.
|
|
| 115 | +--
|
|
| 116 | +-- >>> read "123" :: Int
|
|
| 117 | +-- 123
|
|
| 118 | +--
|
|
| 119 | +-- >>> read "hello" :: Int
|
|
| 120 | +-- *** Exception: Prelude.read: no parse
|
|
| 121 | +read :: Read a => String -> a
|
|
| 122 | +read s = either errorWithoutStackTrace id (readEither s) |
| ... | ... | @@ -329,7 +329,6 @@ Library |
| 329 | 329 | GHC.Internal.System.Posix.Types
|
| 330 | 330 | GHC.Internal.Text.ParserCombinators.ReadP
|
| 331 | 331 | GHC.Internal.Text.ParserCombinators.ReadPrec
|
| 332 | - GHC.Internal.Text.Read
|
|
| 333 | 332 | GHC.Internal.Text.Read.Lex
|
| 334 | 333 | GHC.Internal.Text.Show
|
| 335 | 334 | GHC.Internal.Type.Reflection
|
| ... | ... | @@ -46,7 +46,7 @@ import GHC.Internal.IO.Encoding.Types |
| 46 | 46 | import qualified GHC.Internal.IO.Encoding.Iconv as Iconv
|
| 47 | 47 | #else
|
| 48 | 48 | import qualified GHC.Internal.IO.Encoding.CodePage as CodePage
|
| 49 | -import GHC.Internal.Text.Read (reads)
|
|
| 49 | +import GHC.Internal.Text.Read (readsPrec)
|
|
| 50 | 50 | #endif
|
| 51 | 51 | import qualified GHC.Internal.IO.Encoding.Latin1 as Latin1
|
| 52 | 52 | import qualified GHC.Internal.IO.Encoding.UTF8 as UTF8
|
| ... | ... | @@ -319,7 +319,8 @@ mkTextEncoding' cfm enc = |
| 319 | 319 | _ | isAscii -> return (Latin1.mkAscii cfm)
|
| 320 | 320 | _ | isLatin1 -> return (Latin1.mkLatin1_checked cfm)
|
| 321 | 321 | #if defined(mingw32_HOST_OS)
|
| 322 | - 'C':'P':n | [(cp,"")] <- reads n -> return $ CodePage.mkCodePageEncoding cfm cp
|
|
| 322 | + 'C':'P':n | [(cp,"")] <- readsPrec 0 n -> return $ CodePage.mkCodePageEncoding cfm cp
|
|
| 323 | + -- 'readsPrec 0' is the same as 'reads', but 'reads' is only defined in @base@.
|
|
| 323 | 324 | _ -> unknownEncodingErr (enc ++ codingFailureModeSuffix cfm)
|
| 324 | 325 | #else
|
| 325 | 326 | -- Otherwise, handle other encoding needs via iconv.
|
| 1 | -{-# LANGUAGE Trustworthy #-}
|
|
| 2 | -{-# LANGUAGE NoImplicitPrelude #-}
|
|
| 3 | - |
|
| 4 | ------------------------------------------------------------------------------
|
|
| 5 | --- |
|
|
| 6 | --- Module : GHC.Internal.Text.Read
|
|
| 7 | --- Copyright : (c) The University of Glasgow 2001
|
|
| 8 | --- License : BSD-style (see the file libraries/base/LICENSE)
|
|
| 9 | ---
|
|
| 10 | --- Maintainer : libraries@haskell.org
|
|
| 11 | --- Stability : provisional
|
|
| 12 | --- Portability : non-portable (uses Text.ParserCombinators.ReadP)
|
|
| 13 | ---
|
|
| 14 | --- Converting strings to values.
|
|
| 15 | ---
|
|
| 16 | --- The "Text.Read" library is the canonical library to import for
|
|
| 17 | --- 'Read'-class facilities. For GHC only, it offers an extended and much
|
|
| 18 | --- improved 'Read' class, which constitutes a proposed alternative to the
|
|
| 19 | --- Haskell 2010 'Read'. In particular, writing parsers is easier, and
|
|
| 20 | --- the parsers are much more efficient.
|
|
| 21 | ---
|
|
| 22 | ------------------------------------------------------------------------------
|
|
| 23 | - |
|
| 24 | -module GHC.Internal.Text.Read (
|
|
| 25 | - -- * The 'Read' class
|
|
| 26 | - Read(..),
|
|
| 27 | - ReadS,
|
|
| 28 | - |
|
| 29 | - -- * Haskell 2010 functions
|
|
| 30 | - reads,
|
|
| 31 | - read,
|
|
| 32 | - readParen,
|
|
| 33 | - lex,
|
|
| 34 | - |
|
| 35 | - -- * New parsing functions
|
|
| 36 | - module GHC.Internal.Text.ParserCombinators.ReadPrec,
|
|
| 37 | - L.Lexeme(..),
|
|
| 38 | - lexP,
|
|
| 39 | - parens,
|
|
| 40 | - readListDefault,
|
|
| 41 | - readListPrecDefault,
|
|
| 42 | - readEither,
|
|
| 43 | - readMaybe
|
|
| 44 | - |
|
| 45 | - ) where
|
|
| 46 | - |
|
| 47 | -import GHC.Internal.Base (String, id, return)
|
|
| 48 | -import GHC.Internal.Err (errorWithoutStackTrace)
|
|
| 49 | -import GHC.Internal.Maybe (Maybe(..))
|
|
| 50 | -import GHC.Internal.Read
|
|
| 51 | -import GHC.Internal.Data.Either
|
|
| 52 | -import GHC.Internal.Text.ParserCombinators.ReadP as P
|
|
| 53 | -import GHC.Internal.Text.ParserCombinators.ReadPrec
|
|
| 54 | -import qualified GHC.Internal.Text.Read.Lex as L
|
|
| 55 | - |
|
| 56 | --- $setup
|
|
| 57 | --- >>> import Prelude
|
|
| 58 | - |
|
| 59 | -------------------------------------------------------------------------
|
|
| 60 | --- utility functions
|
|
| 61 | - |
|
| 62 | --- | equivalent to 'readsPrec' with a precedence of 0.
|
|
| 63 | -reads :: Read a => ReadS a
|
|
| 64 | -reads = readsPrec minPrec
|
|
| 65 | - |
|
| 66 | --- | Parse a string using the 'Read' instance.
|
|
| 67 | --- Succeeds if there is exactly one valid result.
|
|
| 68 | --- A 'Left' value indicates a parse error.
|
|
| 69 | ---
|
|
| 70 | --- >>> readEither "123" :: Either String Int
|
|
| 71 | --- Right 123
|
|
| 72 | ---
|
|
| 73 | --- >>> readEither "hello" :: Either String Int
|
|
| 74 | --- Left "Prelude.read: no parse"
|
|
| 75 | ---
|
|
| 76 | --- @since base-4.6.0.0
|
|
| 77 | -readEither :: Read a => String -> Either String a
|
|
| 78 | -readEither s =
|
|
| 79 | - case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
|
|
| 80 | - [x] -> Right x
|
|
| 81 | - [] -> Left "Prelude.read: no parse"
|
|
| 82 | - _ -> Left "Prelude.read: ambiguous parse"
|
|
| 83 | - where
|
|
| 84 | - read' =
|
|
| 85 | - do x <- readPrec
|
|
| 86 | - lift P.skipSpaces
|
|
| 87 | - return x
|
|
| 88 | - |
|
| 89 | --- | Parse a string using the 'Read' instance.
|
|
| 90 | --- Succeeds if there is exactly one valid result.
|
|
| 91 | ---
|
|
| 92 | --- >>> readMaybe "123" :: Maybe Int
|
|
| 93 | --- Just 123
|
|
| 94 | ---
|
|
| 95 | --- >>> readMaybe "hello" :: Maybe Int
|
|
| 96 | --- Nothing
|
|
| 97 | ---
|
|
| 98 | --- @since base-4.6.0.0
|
|
| 99 | -readMaybe :: Read a => String -> Maybe a
|
|
| 100 | -readMaybe s = case readEither s of
|
|
| 101 | - Left _ -> Nothing
|
|
| 102 | - Right a -> Just a
|
|
| 103 | - |
|
| 104 | --- | The 'read' function reads input from a string, which must be
|
|
| 105 | --- completely consumed by the input process. 'read' fails with an 'error' if the
|
|
| 106 | --- parse is unsuccessful, and it is therefore discouraged from being used in
|
|
| 107 | --- real applications. Use 'readMaybe' or 'readEither' for safe alternatives.
|
|
| 108 | ---
|
|
| 109 | --- >>> read "123" :: Int
|
|
| 110 | --- 123
|
|
| 111 | ---
|
|
| 112 | --- >>> read "hello" :: Int
|
|
| 113 | --- *** Exception: Prelude.read: no parse
|
|
| 114 | -read :: Read a => String -> a
|
|
| 115 | -read s = either errorWithoutStackTrace id (readEither s) |
| ... | ... | @@ -3,6 +3,6 @@ pattern (:+_0) :: GHC.Internal.Types.Int -> |
| 3 | 3 | (GHC.Internal.Types.Int, GHC.Internal.Types.Int)
|
| 4 | 4 | pattern x_1 :+_0 y_2 = (x_1, y_2)
|
| 5 | 5 | pattern A_0 :: GHC.Internal.Types.Int -> GHC.Internal.Base.String
|
| 6 | -pattern A_0 n_1 <- (GHC.Internal.Text.Read.read -> n_1) where
|
|
| 6 | +pattern A_0 n_1 <- (Text.Read.read -> n_1) where
|
|
| 7 | 7 | A_0 0 = "hi"
|
| 8 | 8 | A_0 1 = "bye" |
| ... | ... | @@ -11,14 +11,13 @@ subsumption_sort_hole_fits.hs:2:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdef |
| 11 | 11 | words :: String -> [String]
|
| 12 | 12 | (imported from ‘Prelude’
|
| 13 | 13 | (and originally defined in ‘GHC.Internal.Data.OldList’))
|
| 14 | - read :: forall a. Read a => String -> a
|
|
| 15 | - with read @[String]
|
|
| 16 | - (imported from ‘Prelude’
|
|
| 17 | - (and originally defined in ‘GHC.Internal.Text.Read’))
|
|
| 18 | 14 | repeat :: forall a. a -> [a]
|
| 19 | 15 | with repeat @String
|
| 20 | 16 | (imported from ‘Prelude’
|
| 21 | 17 | (and originally defined in ‘GHC.Internal.List’))
|
| 18 | + read :: forall a. Read a => String -> a
|
|
| 19 | + with read @[String]
|
|
| 20 | + (imported from ‘Prelude’ (and originally defined in ‘Text.Read’))
|
|
| 22 | 21 | mempty :: forall a. Monoid a => a
|
| 23 | 22 | with mempty @(String -> [String])
|
| 24 | 23 | (imported from ‘Prelude’
|
| ... | ... | @@ -6,6 +6,9 @@ T21130.hs:10:6: error: [GHC-88464] |
| 6 | 6 | In an equation for ‘x’: x = (_ f) :: Int
|
| 7 | 7 | • Relevant bindings include x :: Int (bound at T21130.hs:10:1)
|
| 8 | 8 | Valid hole fits include
|
| 9 | + read :: forall a. Read a => String -> a
|
|
| 10 | + with read @Int
|
|
| 11 | + (imported from ‘Prelude’ (and originally defined in ‘Text.Read’))
|
|
| 9 | 12 | head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
|
| 10 | 13 | with head @Int
|
| 11 | 14 | (imported from ‘Prelude’
|
| ... | ... | @@ -14,10 +17,6 @@ T21130.hs:10:6: error: [GHC-88464] |
| 14 | 17 | with last @Int
|
| 15 | 18 | (imported from ‘Prelude’
|
| 16 | 19 | (and originally defined in ‘GHC.Internal.List’))
|
| 17 | - read :: forall a. Read a => String -> a
|
|
| 18 | - with read @Int
|
|
| 19 | - (imported from ‘Prelude’
|
|
| 20 | - (and originally defined in ‘GHC.Internal.Text.Read’))
|
|
| 21 | 20 | |
| 22 | 21 | T21130.hs:10:8: error: [GHC-39999]
|
| 23 | 22 | • Ambiguous type variable ‘t0’ arising from a use of ‘f’
|