Por que a `cabeça 'de Haskell trava em uma lista vazia (ou por que * não * retorna uma lista vazia)? (Filosofia da linguagem)

Nota a outros contribuidores em potencial: por favor, não hesite em usar anotações abstratas ou matemáticas para expressar sua opinião. Se a sua resposta não for clara, solicitarei esclarecimentos, mas fique à vontade para se expressar de uma maneira confortáve

Para ser claro: eu sounã procurando um "seguro"head, nem é a escolha dehead em particular excepcionalmente significativo. A questão principal segue a discussão dehead ehead', que servem para fornecer contexto.

Estou hackeando Haskell há alguns meses (até o ponto em que ele se tornou minha língua principal), mas reconhecidamente não estou bem informado sobre alguns dos conceitos mais avançados nem os detalhes da filosofia da linguagem ( embora eu esteja mais do que disposto a aprender). Minha pergunta então não é tão técnica (a menos que seja e eu simplesmente não a percebo) quanto é de filosofia.

Para este exemplo, estou falando dehead.

Como eu imagino que você saiba,

Prelude> head []    
*** Exception: Prelude.head: empty list

Isso segue dehead :: [a] -> a. Justo. Obviamente, não se pode retornar um elemento de nenhum tipo (com a mão acenando). Mas, ao mesmo tempo, é simples (se não trivial) definir

head' :: [a] -> Maybe a
head' []     = Nothing
head' (x:xs) = Just x

Vi algumas discussões sobre issoAqu na seção de comentários de determinadas declarações. Notavelmente, um Alex Stangl diz

'Existem boas razões para não tornar tudo "seguro" e lançar exceções quando as condições prévias são violadas.'

Não questiono necessariamente essa afirmação, mas estou curioso para saber quais são essas "boas razões"

Além disso, um Paul Johnson di

'Por exemplo, você pode definir "safeHead :: [a] -> Talvez a", mas agora, em vez de lidar com uma lista vazia ou provar que isso não pode acontecer, você precisa lidar com "Nothing" ou provar que não pode acontecer.'

O tom que li desse comentário sugere que esse é um aumento notável na dificuldade / complexidade / algo assim, mas não tenho certeza se entendo o que ele está colocando lá for

Um Steven Pruzina diz (em 2011, nada menos),

"Há uma razão mais profunda pela qual, por exemplo, 'head' não pode ser à prova de colisão. Para ser polimórfico e ainda assim lidar com uma lista vazia, 'head' deve sempre retornar uma variável do tipo que está ausente em qualquer lista vazia em particular. seja Delphic se Haskell pudesse fazer isso ... ".

O polimorfismo é perdido ao permitir o processamento de listas vazias? Se sim, como e por quê? Existem casos particulares que tornariam isso óbvio?Esta seção é amplamente respondida por @Russell O'Conno Qualquer pensamento adicional é, obviamente, apreciad

Vou editar isso conforme a clareza e a sugestão. Quaisquer pensamentos, documentos, etc., que você possa fornecer serão muito apreciado

questionAnswers(6)

yourAnswerToTheQuestion