[GHC] #13028: Compile-time validation of literals in IsString instances
GHC
ghc-devs at haskell.org
Thu Dec 22 08:45:21 UTC 2016
#13028: Compile-time validation of literals in IsString instances
-------------------------------------+-------------------------------------
Reporter: jml | Owner:
Type: feature | Status: new
request |
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
I would like to be able to make `IsString` instances using the
`OverloadedStrings` extension such that my instance rejects some literals
as being invalid and such that that rejection happens at compile time, so
that programming mistakes don't make it into the code I give to my users.
I have a couple of use cases where I have a `Name` type that only admits
certain strings. e.g.
{{{#!hs
module Name (Name(getName), makeName) where
import Data.Text (Text)
import qualified Data.Text as Text
-- | A guaranteed non-empty name.
newtype Name = Name { getName :: Text } deriving (Eq, Show, Ord)
makeName :: Text -> Maybe Name
makeName name
| Text.null name = Nothing
| otherwise = Just name
}}}
In a real use case, I'd check for valid characters, not starting with a
digit, that sort of thing.
The idea is that we don't export the `Name` constructor, which means
anyone using a `Name` value can trust that it has certain properties (in
this case, non-empty).
My problem is that I'd like to use literal names in many places. e.g.
{{{#!hs
programName :: Name
programName = fromJust $ makeName "the-great-and-powerful-turtle"
}}}
Because I do this a lot, I've defined an `unsafeMakeName` helper that does
pretty much the same thing:
{{{#!hs
unsafeMakeName :: Text -> Name
unsafeMakeName name = fromMaybe (error $ "Invalid name: " <> Text.unpack
name) (makeName name)
}}}
The problem with this approach is that even though the cause of the
mistake is a programming error, I don't find out about it until run time.
What I'd like to do is write an `IsString` instance for `Name` which does
that validation, e.g.
{{{#!hs
instance IsString Name where
fromString = unsafeMakeName . Text.pack
}}}
... but to get the error about invalid names in literals at compile-time.
This doesn't seem logically impossible to me, since the compiler could
know the values of literals with certainty.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13028>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list