7
votes

Évaluation des fonctions nulaires à Haskell

Supposons que vous ayez une fonction nulle dans HASKELLL, qui est utilisée plusieurs fois dans le code. Est-ce toujours évalué qu'une seule fois? J'ai déjà testé le code suivant:

test _ 0 = []
test s n = (s:(test (n-1)))
...
test sayHello 10


0 commentaires

3 Réponses :


17
votes

Il n'y a pas de fonctionnalité nullaire. Une fonction de Haskell a exactement un argument et a toujours le type ... -> ... . Sayhello est une valeur - un int - mais pas une fonction. Voir Cet article Pour plus.

sur les garanties: Non, vous n'obtenez pas vraiment de garanties. Le rapport HASKELL Spécifie que Haskell n'est pas strict - vous savez donc quelles sont les choses de la valeur qui finiront par réduire - mais pas une stratégie d'évaluation particulière. La stratégie d'évaluation GHC utilise généralement est évaluation paresseuse , c'est-à-dire une évaluation non stricte avec le partage, mais cela ne Il faut des garanties fortes à ce sujet - l'optimiseur pourrait mélanger votre code autour de sorte que les choses soient évaluées plus d'une fois.

Il existe également différentes exceptions - par exemple, foo :: num A => A est polymorphe, il ne sera probablement pas partagé (il est compilé à une fonction réelle). Parfois, une valeur pure peut être évaluée par plus d'un fil en même temps (qui ne se produira pas dans ce cas car inadaperformio utilise explicitement noduplicate pour l'éviter). Ainsi, lorsque vous programmez, vous pouvez généralement attendre la paresse , mais si vous voulez une sorte de garantie, vous devez faire très attention. Le rapport lui-même ne vous donnera rien vraiment sur comment votre programme est évalué.

Unsafeperformio vous donne encore moins dans la voie des garanties, bien sûr. Il y a une raison pour laquelle il s'appelle "dangereux".


0 commentaires

5
votes

Niveau supérieur Niveau non-argument Fonctions telles que Sayhello sont appelées formes applicatives constantes et sont toujours mémoisées (au moins dans GHC - voir http://www.hakell.org/ghc/docs/7.2.1/html/users_guide/profiling.html ). Vous devriez avoir recours à des astuces comme en passant des arguments factices et de transformer des optimisations sur pas partager un CAF globalement.

Modifier : Devis du lien ci-dessus -

Haskell est un langage paresseux et certaines expressions ne sont que jamais évalué une fois. Par exemple, si nous écrivons: x = nfib 25 alors x ne sera évalué qu'une seule fois (le tout), et Les demandes ultérieures pour x vont immédiatement voir le résultat mis en cache. La définition x est appelée formulaire de CAF (formulaire d'application constante), car Il n'a aucun argument.


0 commentaires

1
votes

Si vous voulez "Bonjour" imprimé n Times, vous devez supprimer le nonafeperformio indicatif>, de sorte que l'exécution saura qu'elle ne peut pas optimiser les appels répétés vers Poststr CODE> . Je ne suis pas clair si vous souhaitez renvoyer la liste des int, j'ai donc écrit deux versions de test, l'une des revenues (), une [int].

sayHello2 :: IO Int
sayHello2 = do
    putStr "Hello"
    return 42

test2 :: Int -> IO ()
test2 0 = return ()
test2  n = do
  sayHello2
  test2 (n-1)

test3 :: Int -> IO [Int]
test3 0 = return []
test3 n = do
  r <- sayHello2
  l <- test3 (n-1)
  return $ r:l


0 commentaires