haskell ghc string-literals overloaded-strings

haskell - Restringir literales de cadena a solo texto



ghc string-literals (2)

Soy consciente de que el lenguaje pragma OverloadedStrings envuelve implícita fromString alrededor de todos los literales de cadena. Lo que me gustaría hacer es no sobrecargar las cadenas, sino simplemente cambiar su significado para que siempre se conviertan en Text , y por lo tanto, usar un literal de cadena como una lista de caracteres debería resultar en un error de tipo.

Parece imposible importar la clase IsString sin importar también la instancia de String para esa clase. ¿Ghc me proporciona alguna forma de restringir los literales de cadena a solo Text ?


Es un poco exagerado, pero una solución es combinar OverloadedStrings y RebindableSyntax . La extensión RebindableSyntax causa que todas las llamadas a funciones implícitas que usa la sintaxis Haskell se refieran a cualquier función que esté dentro del alcance; por ejemplo, los literales enteros usan cualquiera de fromIntegral , no necesariamente Prelude.fromIntegral . Como efecto secundario, Prelude ya no se importa implícitamente, por lo que debe hacerlo manualmente. Mientras lo importe, no debería haber ningún problema con la sintaxis que use la función incorrecta implícitamente (creo que no he usado esta técnica). Cuando se combina con OverloadedStrings , esto hace que "foo" se transforme en fromString "foo" para el fromString cualquier fromString , no necesariamente Data.String.fromString "foo" . Así que hacer fromString con el pack hará lo que quieras. Un ejemplo completo:

{-# LANGUAGE OverloadedStrings, RebindableSyntax #-} import Prelude import qualified Data.Text as T import qualified Data.Text.IO as T fromString :: String -> T.Text fromString = T.pack main :: IO () main = T.putStrLn "Hello, world!"

Esto funciona bien, y cambiando main a main = putStrLn "Hello, world!" produce el error deseado:

TestStrings.hs:11:17: Couldn''t match expected type `String'' with actual type `T.Text'' Expected type: [Char] -> String Actual type: String -> T.Text In the first argument of `putStrLn'', namely `"Hello, world!"'' In the expression: putStrLn "Hello, world!"

Comentando la definición de fromString causa un error diferente:

TestStrings.hs:11:19: Not in scope: `fromString'' Perhaps you meant `showString'' (imported from Prelude)

Si desea que funcione con texto estricto y perezoso, puede definir su propia clase de tipo IsString y convertir ambas instancias; la clase no tiene que llamarse IsString , siempre que tenga un método fromString .

Además, una palabra de advertencia: la sección del manual de GHC sobre RebindableSyntax no menciona la función fromString , y la sección sobre OverloadedStrings no menciona RebindableSyntax . No hay razón para que esto no funcione, pero creo que eso significa que esta solución se basa técnicamente en un comportamiento no documentado.


No es una forma de lograr esto ahora, pero tal vez con el tiempo, es la instance force como se propone en una propuesta de característica GHC en discusión , donde diría

instance force IsString Text

en tu módulo Este es uno de los principales ejemplos de motivación para la propuesta.