2016-11-15 4 views
2

Pour une classe, j'essayais de trouver des exemples simples de fonctions strictes et non-strictes, soutenant que les fonctions non-strictes avaient du sens. Un de mes exemples était qu'il pourrait être utile de définir 0 * x = x * 0 = 0 pour tout x dans le domaine. Quand je suis rentré chez moi, je voulais naturellement voir ce que les créateurs Haskell pensent de ça. Voici ma confusion.multiplication stricte ou non stricte dans haskell?

à une machine, ghci dit que la multiplication est stricte sur les deux arguments:

GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> 0 * undefined 
*** Exception: Prelude.undefined 
Prelude> undefined * 0 
*** Exception: Prelude.undefined 

à une autre machine, ghci dit que la multiplication est non stricte sur le premier argument:

GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help 
Prelude> undefined * 0 
0 
Prelude> 0 * undefined 
*** Exception: Prelude.undefined 

Qu'est-ce que provoque la différence de comportement?

+0

Je ne connais pas la réponse à votre question, mais des exemples de pourquoi la paresse est utile que vous pourriez aimer [non-Trivial évaluation Lazy] (http://stackoverflow.com/questions/7868507/évaluation non-triviale-paresseuse). –

+5

C'est le résultat d'un [bug dans GHC 7.10.3] (http://stackoverflow.com/questions/36049689/why-dul-multiplication-only-short-circuit-on-one-side) qui n'a pas exister avant 7.10 et a été éliminé en 8.1. –

+0

OK. Merci. Savez-vous quel est le raisonnement derrière la décision de rendre la multiplication stricte? De mon point de vue, ce n'est pas évident, parce que je fais un parallèle avec le fait que True || undefined = Vrai. – stefk0

Répondre

1

La réponse est dans les commentaires grâce à @DavidYoung - c'est un bug GHC rien de plus.

Si vous souhaitez que la multiplication soit paresseuse d'une certaine manière, vous pouvez certainement écrire votre propre type et instance pour Num. Par exemple:

module Main where 

main :: IO() 
main = 
    do print (one * two) 
    print (undefined * zero) 
    putStrLn "The next one has an exception because it must evaluate the undefined arugment." 
    print (undefined * two) 

one, two, zero :: LazyInt 
one = 1 
two = 2 
zero = 0 

-- Not fully lazy such as in addition or Ord, which is possible, 
-- but just in the first argument for multiplication. 
newtype LazyInt = LI { unLI :: Int } 
       deriving (Eq, Ord) 

instance Show LazyInt where 
    show (LI x) = show x 

instance Num LazyInt where 
    (LI a) + (LI b) = LI (a + b) 
    negate (LI a) = LI (negate a) 
    abs (LI a) = LI (abs a) 
    signum (LI a) = LI (signum a) 
    fromInteger i = LI (fromInteger i) 

    -- The case of interest: 
    a * (LI b) = 
    if b == 0 
     then LI 0 
     else LI (unLI a * b)