2016-11-15 20 views
2

クラスについては、厳密でない関数の単純な例を考え出し、非厳密な関数が意味をなさないと主張していました。私の例の1つは、ドメイン内のすべてのxに対して0 * x = x * 0 = 0を定義することが有用かもしれないということでした。私が家に帰ったとき、私は自然にハスケルのクリエイターがそれについて何を考えているのか見たいと思っていました。ここに私の混乱が来る。一台のマシンでhaskellでの厳密なまたは非厳密な乗算?

、GHCiの乗算は、両方の引数に厳密であることを言う:別のマシンで

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 

、GHCiのは、乗算が最初の引数に非厳密であることを言う:

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

何行動の違いを引き起こしますか?

+0

[非自明レイジー評価](http://stackoverflow.com/questions/7868507例えば: /非自明 - 遅延評価)。 –

+5

これは、[GHC 7.10.3のバグ](http://stackoverflow.com/questions/36049689/why-does-multiplication-only-short-circuit-on-one-side)の結果です。 7.10より前に存在し、8.1で削除されました。 –

+0

OK。ありがとう。乗算を厳密にするという決定の背後にある理由は何ですか?私の見解では、これは明らかではありません。なぜなら、私は真実と平行しているからです。 undefined = True。 – stefk0

答えて

1

答えは@DavidYoungのおかげです。これはGHCのバグです。

特定の方法で乗算を遅延させるには、Numの独自の型とインスタンスを作成できます。私はあなたの質問への答えを知っているが、怠惰はあなたが好きかもしれない便利である理由の例はありません

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)