Sobre Text e OverloadedStrings
por Pedro Tacla Yamada
Essa é uma nota rápida para completar o
dia 4 da série 24 dias de Hackage. Vou
comentar brevemente sobre a extensão OverloadedStrings e os tipos String,
ByteString e Text.
Você pode ter notado que Haskell tem mais de um tipo para representar texto.
Isso é, de fato, um problema do ecossistema da linguagem, mas não vale a pena
discutir as críticas a fundo. Como expliquei
no primeiro post desse blog em português
o literal [1, 2, 3] em Haskell é uma lista-ligada, não um Array. O tipo
String em Haskell também é uma lista:
type String = [Char]Você pode imaginar que isso causa problemas de performance, porque listas não são a melhor estrutura de dados para muitas tarefas relacionadas a processamento de texto.
Por isso, há dois pacotes que implementam tipos para strings com características diferentes:
Ambos os pacotes seguem a convenção de exportar funções pack que recebem uma
String e retornam um Text ou uma ByteString. O que a extensão
OverloadedStrings faz é usar uma type-class definida em Data.String chamada
IsString. A type-class define:
class IsString s where
fromString :: String -> sAlgumas implementações da type-class seriam:
instance IsString String where
fromString = id
instance IsString Text where
fromString = packAssim, quando escrevemos o literal "asdfasdf" no código a extensão vai
reescrever isso como (fromString "asdfasdf"). Isso nos deixa ter
"asdfasdf" :: String e "asdfasdf" :: Text. Na maior parte dos casos o
compilador vai só inferir o tipo certo e as coisas vão funcionar fluidamente.
Outra extensão na mesma linha é OverloadedLists.
Ela usa type-class IsList, que é basicamente definida como:
class IsList l where
type Item l
fromList :: [Item l] -> lIsso quer dizer que uma instância para um “tipo alvo” tem que definir um tipo de
elemento e poderemos converter literais de listas desse tipo para o “tipo alvo”.
Em outras palavras, se queremos escrever Sets do
Data.Set
como listas, adicionamos a instância:
import qualified Data.Set
instance (Ord a) => IsList (Data.Set.Set a) where
type Item (Data.Set.Set a) = a
fromList = Data.Set.fromListAo ativar a extensão se pode escrever
[1, 2, 3, 4] :: Data.Set.SetConhecendo essas extensões o problema não parece tão ruim assim. Acabo de mostrar uma forma com a qual Haskell nos deixa ter literais para tipos definidos pelo usuário. Estou curioso sobre quais outras linguagens que te permitem fazer isso.
