Por que Prelude.read de Haskell não retorna um Maybe?

108

Existe uma boa razão para o tipo de Prelude.read ser

read :: Read a => String -> a

em vez de retornar um Maybevalor?

read :: Read a => String -> Maybe a

Já que a string pode não ser analisável por Haskell, o último não seria mais natural?

Ou até mesmo um Either String a, onde Leftconteria a string original se não fosse analisada eRight o resultado se sim?

Editar:

Não estou tentando fazer com que outras pessoas escrevam um wrapper correspondente para mim. Apenas buscando a garantia de que é seguro fazer isso.

Bilal Barakat
fonte
14
Por que não takeaceita nenhum Num a => a? Por que existe um caso especial de fmaplistas para? Por que Functornão é necessário para Monadinstâncias? Espero que a resposta seja semelhante às respostas a essas perguntas e outras relacionadas.
3
Bem, é por isso que eu coloquei dessa maneira, deixando em aberto a opção de que não há um bom motivo. Embora eu também suspeite que pode não haver, como para os exemplos bem conhecidos que você dá, vale a pena perguntar para ter certeza de que escrever meu próprio invólucro não criará problemas imprevistos no fluxo.
Bilal Barakat
Espero que uma readMaybefunção seja adicionada em breve.
agosto
Bons pontos @delnan, mas não deve takeser Integral n => n -> [a] -> [a]?
Doug McClean
@DougMcClean: Sim, deveria ser Integral, não Num- peido cerebral.

Respostas:

106

Editar : a partir do GHC 7.6, readMaybeestá disponível no Text.Readmódulo no pacote básico, junto com readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


Ótima pergunta! O tipo de leitura em si não mudará tão cedo porque isso quebraria muitas coisas. No entanto, deve haver ummaybeRead função.

Por que não existe? A resposta é "inércia". Houve uma discussão em '08 que foi prejudicada por uma discussão sobre "fracasso".

A boa notícia é que as pessoas estavam suficientemente convencidas para começar a se afastar do fracasso nas bibliotecas. A má notícia é que a proposta se perdeu na confusão. Não deve ser tal função um, embora um seja fácil de escrever (e existem zilhões de versões muito semelhantes flutuando muitas bases de código).

Veja também esta discussão .

Pessoalmente, uso a versão do pacote seguro .

sclv
fonte
30

Sim, seria útil com uma função de leitura que retornasse Maybe. Você mesmo pode fazer um:

readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
              [(x, "")] -> Just x
              _ -> Nothing
agosto
fonte
3
Obrigado! Espero que a edição não pareça ingrata! :) Só quero deixar claro que não estou pedindo por preguiça ...
Bilal Barakat
6
Se @augustss não puder fornecer, uma resposta melhor pode não existir.
John L
2
Não acho que uma versão talvez tenha sido discutida no design original. Muitas dessas coisas se tornam óbvias com a experiência, mas podem ser difíceis de prever.
agosto 10/11/11
O motivo pelo qual a leitura retorna uma lista é para o caso em que há várias análises válidas. O caso Maybe é intermediário entre leituras e leituras.
Chris Kuklewicz de
Acho que isso requer uma Read atypeclass:readMaybe :: Read a => String -> Maybe a
David Tchepak
15

Além da inércia e / ou mudanças nas percepções, outro motivo pode ser o fato de ser esteticamente agradável ter uma função que pode atuar como uma espécie de inverso de show. Ou seja, você deseja que read . showseja a identidade (para tipos que são uma instância de Showe Read) e que show . readseja a identidade no intervalo de show(ou seja,show . read . show == show )

Ter um Maybeno tipo de readquebra a simetria com show :: a -> String.

yatima2975
fonte
Obrigado por adicionar um novo ângulo! Isso faz sentido. Mas, para conseguir isso de forma limpa, não faria sentido exibir e ler produzindo um tipo distinto, digamos "ParseableString"?
Bilal Barakat
1
@BilalBarakat: O tipo distinto pode ser newtype ValidShow a = ValidShow String. O tipo fantasma torna mais seguro o tipo.
yairchu de
9
É um ponto interessante, mas no final das contas, uma falsa simetria. Os programadores devem valorizar a correção em vez da estética.
Matt Fenwick
1
@yairchu Não ficou imediatamente óbvio para mim o que você quis dizer sobre o tipo fantasma, então vou esclarecer caso mais alguém esteja confuso como eu. Você pretende algo como showThing :: Show a => a -> ValidShow ae readThing :: Read a => ValidShow a -> a, para que o tipo da coisa que foi mostrada seja lembrada no objeto ValidShow. Assim você não pode escrever readThing (showThing True) :: String.
Amalloy
12

Como @augustss apontou, você pode criar sua própria função de leitura segura. No entanto, seureadMaybe não é totalmente consistente com read, já que não ignora os espaços em branco no final de uma string. (Cometi este erro uma vez, não me lembro bem do contexto)

Olhando para a definição de leitura no relatório Haskell 98 , podemos modificá-la para implementar um readMaybeque seja perfeitamente consistente com read, e isso não é muito inconveniente porque todas as funções das quais depende estão definidas no Prelúdio:

readMaybe        :: (Read a) => String -> Maybe a
readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                         [x] -> Just x
                         _   -> Nothing
serralheiro
fonte
1
Obrigado! 1 por me alertar sobre o problema de espaço em branco, que não havia sido explicitado antes.
Bilal Barakat
3
Observe que se você apenas usar o safepacote, obterá uma versão correta do readMaybedisponível (é chamado readMaye é idêntico a esta versão.
Neil Mitchell
8

Esta função (chamada readMaybe) está agora no prelúdio de Haskell! (A partir da base atual - 4,6)

amindfv
fonte
2
Bem, o texto do link diz que está no Text.Read e não no Prelude (pode ter mudado), no entanto, ainda me ajudou!
Kapichu