Note aux autres contributeurs potentiels : N'hésitez pas à utiliser des notations abstraites ou mathématiques pour faire valoir votre point de vue. Si je trouve que votre réponse n'est pas claire, je demanderai des éclaircissements, mais sinon, n'hésitez pas à vous exprimer de manière confortable.
Pour être clair : je suis no à la recherche d'un "coffre-fort" head
ni le choix de head
en particulier exceptionnellement significatif. L'essentiel de la question suit la discussion sur head
y head'
qui servent à fournir un contexte.
J'utilise Haskell depuis quelques mois maintenant (au point qu'il est devenu mon langage principal), mais j'admets ne pas être bien informé sur certains des concepts les plus avancés ni sur les détails de la philosophie du langage (bien que je sois plus que désireux d'apprendre). Ma question n'est donc pas tant une question technique (à moins qu'elle ne le soit et que je ne m'en rende pas compte) qu'une question de philosophie.
Pour cet exemple, je parle de head
.
Comme vous le savez, j'imagine,
Prelude> head []
*** Exception: Prelude.head: empty list
Cela découle de head :: [a] -> a
. C'est normal. Il est évident que l'on ne peut pas renvoyer un élément qui n'a pas de type. Mais en même temps, il est simple (si ce n'est trivial) de définir
head' :: [a] -> Maybe a
head' [] = Nothing
head' (x:xs) = Just x
J'ai vu quelques petites discussions à ce sujet aquí dans la section des commentaires de certaines déclarations. Notamment, un certain Alex Stangl dit
Il existe de bonnes raisons de ne pas rendre tout "sûr" et de ne pas lever des exceptions lorsque les conditions préalables sont violées.
Je ne remets pas nécessairement en cause cette affirmation, mais je suis curieux de savoir quelles sont ces "bonnes raisons".
En outre, un Paul Johnson dit,
Par exemple, vous pourriez définir "safeHead : : [a] -> Maybe a", mais maintenant, au lieu de gérer une liste vide ou de prouver que cela ne peut pas arriver, vous devez gérer "Rien" ou prouver que cela ne peut pas arriver.
Le ton que je lis dans ce commentaire suggère qu'il s'agit d'une augmentation notable de la difficulté/complexité/quelque chose, mais je ne suis pas sûr de comprendre ce qu'il veut dire.
Un certain Steven Pruzina dit (en 2011, pas moins) ,
"Il y a une raison plus profonde pour laquelle, par exemple, 'head' ne peut pas être à l'épreuve des pannes. Pour être polymorphe tout en gérant une liste vide, 'head' doit toujours retourner une variable du type qui est absent de toute liste vide particulière. Ce serait divin si Haskell pouvait faire cela...".
Le polymorphisme est-il perdu en autorisant la gestion des listes vides ? Si oui, comment, et pourquoi ? Y a-t-il des cas particuliers qui rendraient cela évident ? Cette section a été amplement répondue par @Russell O'Connor. Toute autre réflexion est, bien entendu, la bienvenue.
Je modifierai ce texte en fonction de la clarté et des suggestions. Toute réflexion, tout document, etc., que vous pouvez fournir sera très apprécié.
0 votes
La fonction 'head' n'est pas sûre (elle est partielle, elle n'est pas totale) et ne lève pas d'exception (elle est indéfinie pour une liste vide).