10
votes

Haskell Imprimé pendant la récursion?

foo:: Int -> Int -> Int
foo z x = if (z < 100) 
             then z * foo (z+(x*z)) z
             else z
How would you print out(the integer z) an output every time it gets called from itself?Can you have function that returns an IO and Int? Do you need a secondary function?

0 commentaires

4 Réponses :


4
votes

Toute fonction qui effectue des E / S doit renvoyer son résultat dans le io monad: xxx

remarque que les deux branches du si expression doit maintenant être dans io aussi.

Ce n'est pas la même chose que le retour "An io et int int ". io int est le type d'une valeur qui représente une action d'E / S qui, lorsqu'elle est exécutée, produira un int comme résultat (éventuellement après avoir effectué des E / S) . Donc la définition ci-dessus de foo prend un int et un int et renvoie une action d'E / S qui finira éventuellement à un int .


0 commentaires

19
votes

Pour la simplicité, vous pouvez utiliser Trace . Cependant, il n'est pas accueilli pour un code de production réel car il brise la transparence référentielle. trace code> prend une chaîne code> pour imprimer et une valeur à renvoyer.

import Debug.Trace

foo:: Int -> Int -> Int
foo z x = trace ("z = " ++ show z) $ if (z < 100) 
    then z * foo (z+(x*z)) z
    else z

*Main> foo 1 2
 z = 1
 z = 3
 z = 6
 z = 24
 z = 168
 72576


0 commentaires

11
votes

Pour la complétude, je vais répondre à cette question:

Pouvez-vous avoir une fonction qui renvoie un IO et INT?

... Littéralement. La réponse est "oui!" ... et c'est même parfois utile. Probablement ce n'est pas ce que vous voulez faire en tant que débutant, mais au cas où il est, voici un échantillon. xxx

Par exemple, vous pouvez imprimer les appels récursifs en réglant xxx

ou vous pouvez simplement imprimer la réponse en réglant xxx

ou une demi-douzaine d'autres choses. Bien sûr, le type io () est un peu difficile à inspecter; Vous pouvez envisager d'écrire quelque chose comme ça à la place: xxx

Utilisation est assez similaire à celui ci-dessus, mais avec un Extra Runwriter dans; Par exemple, vous pouvez écrire l'un de ces deux: xxx

L'avantage de cette méthode est que vous récupérez une liste des valeurs d'appel plutôt que d'une action IO qui imprime que liste, afin que vous puissiez munier les appels de nombreuses manières plus intéressantes.


5 commentaires

+1 Nos débutants Haskell devraient être introduits à des choses comme écrivain beaucoup plus tôt que nous les enseignons habituellement.


@Danburton, si nous introduisons x plus tôt, nous devons présenter y plus tard. Quel est Y dans ce cas?


Les compréhensions de liste IMHO @Luqui sont apprises trop tôt. Il est vrai qu'ils sont assez simples de comprendre, mais il est préférable que l'étudiant puisse apprendre l'interface monad réelle puis découvrez la compréhension de la syntaxe de la syntaxe de la compréhension. J'espère que la rédaction de vos propres typeclasses et de vos propres cas devriez venir plus tard, bien que je n'ai pas beaucoup réfléchi aux ramifications de cela.


@Luqui: Je suppose que debug.trace.trace.trace alors


Pourriez-vous commenter les implications de la performance de l'utilisation de écrivain avec une liste au lieu d'un dlist ?



5
votes

bâtiment de la réponse de @ is7s, une idiome utile pour utiliser débog.trace est de faire ceci: xxx

ici, nous avons introduit une définition de FOO avec le TRACE dans un protège qui évalue vers FALSE , de sorte qu'il va toujours tomber à la définition initiale. De cette manière, nous ne perturons pas notre fonction et pouvons transformer le traçage sur ou éteindre en commentant la ligne.


0 commentaires