2013-07-04 3 views
2

Après Caching la résolution d'un problème sur Euler projet, je suis tombé sur le code Haskell suivant dans le forum:Haskell

fillRow115 minLength = cache where 
    cache = ((map fillRow115' [0 ..]) !!) 
    fillRow115' 0 = 1 
    fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1) 

Je viens de commencer l'apprentissage Haskell cette semaine et ne semblent pas comprendre ce code. Quelqu'un peut-il s'il vous plaît expliquer les 2 éléments suivants:

  1. Pour moi, il ressemble il n'y a qu'un seul argument minLength, mais la fonction nécessite 2 arguments pour fonctionner en ghci. Où cet autre argument entre-t-il en jeu? De ce que j'ai pu trouver en ligne, !! est l'opérateur d'index de liste et renvoie le nième élément quand appelé [list] !! n. Le code ci-dessus semble l'appeler avec un seul argument. Qu'est-ce que ça fait?

P.S. Si quelqu'un envisage de copier ce code pour résoudre le problème de Project Euler, il ne semble pas donner la bonne réponse.

Répondre

5

Où cet autre argument entrent en jeu?

Permet de simplifier encore cette question. Vous savez sans doute sur la fonction head:

head [] = error "something bad" 
head (x:_) = x 

Vous pourriez être stupide et définir votre propre fonction de tête qui appelle simplement head:

myHead xs = head xs 

Et remarquez à la fois à gauche et à droite appliquent la xs variable donc nous pouvons faire ce qu'on appelle eta-réduction et aboutir à:

myHead = head 

Les signatures de type peuvent mart int maison:

myHead :: [a] -> a 
myHead = (head :: [a] -> a) 

Donc, dans votre cas, fillRow115 prend un second argument car il est égal à cache, qui prend un argument - et qui nous amène à votre deuxième question.

Le code ci-dessus semble l'appeler avec un seul argument. Qu'est-ce que ça fait?

Considérons la fonction +.Si vous souhaitez faire une fonction qui ajoute toujours 2, vous pouvez « appliquer partiellement » 2 à la fonction +:

addTwo = (+2) -- (2+) would work just as well 

Vous regardez la fonction d'indexation de la liste !!:

(!!) :: [a] -> Int -> a 

Et en disant Pour vous, cela s'applique seulement à certaines listes. L'application de ce que nous savons sur l'application partielle, nous obtenons un type de:

(someList !!) :: Int -> a 

Alors qui est en fait une fonction de Ints à un élément de la liste.

Si cela ne clique pas encore, il suffit de remplacer someList avec la liste que vous utilisez:

someList = map fillRow115' [0..] 
(someList !!) === ((map fillRow 115' [0..]) !!) 
2

Ce concept est appelé partial application.
Cela fonctionne car dans Haskell, toutes les fonctions n'ont qu'un seul paramètre.
Une fonction a -> b -> c pourrait ressembler à une fonction qui prend deux paramètres
(l'un des Typa a, et un de type b), mais il est vraiment une fonction a -> (b -> c),
-à-dire une fonction avec un paramater (de type a) renvoie une fonction qui prend un paramètre (de type b).

Voir http://www.haskell.org/haskellwiki/Partial_application
(ou plus généralement, donner un coup http://learnyouahaskell.com/)