2016-05-20 7 views
1

foreverを見る:「永遠に」例外を投げる?

λ: import Control.Monad 
λ: :t forever 
forever :: Monad m => m a -> m b 

はなぜforever $ Just 42は、数秒後に例外をスローしますか?

λ: forever $ Just 42 
*** Exception: <<loop>> 

forever $ return 4(少なくとも数秒後)?

λ: forever $ return 4 
^C^C^C^Z 
[1]+ Stopped     ghci 
+4

意味が分かります。意味的には、例外と無限ループは区別できません。両方が下位の表記であるためです。意味的には、 'forever(return 0):: Maybe()'と 'forever(return 0):: IO()'の間には*相違がありません。 –

+5

GHCは、「グレイホール」と呼ばれるものを使用して、並行コンテキストで遅延値を処理します。大量のコードを複製するのを避けるため、シングルスレッドのランタイムでもそれらを使用します。デバッグの目的で、「ブラックホール」に変形され、無限ループになることがあります。それはまさに正しい無限ループでなければならず、保証されていません。 – dfeuer

答えて

1

私は完全に慣れていない実装の詳細については説明しませんが、なぜこの動作が望ましいのか、それがどこから来るのかを説明します。

foreverは、我々が

fr x = forever (return x) 

を見れば私たちは

fr x = forever (return x) 
    = return x >> forever (return x) 
    = return x >>= \_ -> fr x 
    = (\_ -> fr x) x 
    = fr x 
を持って

forever x = x >> forever x 

と同等です

forever x = do 
    x 
    forever x 

として定義されます

したがって、基本的にfr xは無限ループです。

ハスケルでは、無限ループとエラーは同じです。

error s = error s 

さて、GHCは、ループのこれらの2つのタイプを区別するために選択されます。ここerrorの一つの可能​​な実装があります。

純粋なコードの無限ループはエラーです。我々は一般的に1つを入力するつもりはなかったし、副作用ではなく価値を求めている。したがって、Maybeでは、無限ループはエラーで終了します。

ただし、純粋なコードで無限ループが一般的です!このコードは、マシンやユーザー入力などで何か他のことが起こるのを待っている可能性があります。

したがって、IOには、実際の無限ループがあります。これは何かを意味します。

関連する問題