Point de départ :
fn :: [a] -> Int
fn = (2 *) . length
Disons que nous seulement nous voulons contraindre la valeur de retour, alors nous pourrions écrire :
fn list = (2 * length list) :: Int
Pourquoi ne pas restreindre seulement l'argument ? Facile.
fn list = 2 * length (list :: [Char])
Bien que cela fonctionne, il serait préférable d'avoir les signatures en haut rassemblées et non dispersées dans le corps de la fonction.
C'est ce qui s'en rapproche le plus :
fnSig = undefined :: [Char] -> a
fn | False = fnSig
| True = (* 2) . length
Sur la base de http://okmij.org/ftp/Haskell/partial-signatures.lhs via http://okmij.org/ftp/Haskell/types.html#partial-sigs
Cependant, j'aimerais une solution plus propre. Quelque chose qui communique mieux que mon intention est une restriction partielle. Quelque chose comme ceci, par exemple :
fn :: [Char] -> a
fn = (2 *) . length
Ou peut-être :
fn :: [Char] -> _
fn = (2 *) . length
Est-ce possible ?
Modifier pour plus de clarté :
@GaneshSittampalam A fait un point important dans un commentaire ci-dessous. Je cherche "une solution à mi-chemin entre l'absence totale de signature de type et la nécessité d'en donner une précise". Donc, je ne cherche pas une réponse basée sur TypeClass, je veux juste que GHC remplisse les blancs pour les types non spécifiés (ou pas complètement restreints) de ma fonction.
Editer en réponse à @WillNess
Oui, quelque chose comme ça...
fn list = 2 * length list
where
_ = list :: [Char]
...pourrait fonctionner, mais seulement pour les arguments, et seulement si la fonction n'est pas sans point. Existe-t-il un moyen d'appliquer cette technique aux fonctions ou aux valeurs de retour sans point ?
Editer en réponse à @Rhymoid
J'ai été inspiré, et j'ai joué avec l'idée de @Rhymoid, et j'ai trouvé ceci :
fn = (2 *) . length
where
_ = fn `asTypeOf` (undefined :: [Char] -> a)
_ = fn `asTypeOf` (undefined :: a -> Int)
_ = fn `asTypeOf` (undefined :: a -> b)
_ = fn `asTypeOf` (undefined :: a)
Cette approche restreint également la signature de type de fn, et ne pollue aucun espace de nom.
D'ordinaire, nous n'aurions qu'une seule des asTypeOf
J'ai juste ajouté plusieurs lignes pour montrer à quel point cette approche est puissante.
C'est un peu plus maladroit que ce que j'aurais souhaité, mais je pense que c'est assez intéressant de pouvoir le faire même sans support syntaxique spécifique du langage.
@Rhymoid, si vous l'aimez aussi, ajoutez-la à votre réponse :)