2011-08-27 5 views
4

(SWI) Prolog 출신 하스켈이 출력을 즉시 출력하도록하는 것은 매우 어렵습니다.실행중인 haskell 프로그램에서 출력 생성

간단한 예를 들어, 나는 하스켈 모든 반복에 뭔가를 인쇄하고 싶습니다 ...

fac 0 = 1 
fac n = fac (n-1) * n 

아니면이 중단 결코 프로그램의 출력을 좀하고 싶습니다

-- A possible halt statement... 
-- find_primes l 100 = l 
find_primes l n = if (is_prime l n) then find_primes nn s else find_primes l s 
where s = n + 1 
nn = n:l 

is_prime :: Integral a => [a] -> a -> Bool 
is_prime [] n = True --print the prime number on the fly  
is_prime (h:t) n = if (r /= 0) then is_prime t n else False 
where r = n mod h 

서곡> find_primes는 [] 2

답변

13

당신은 세 가지 옵션이

먼저 : 0,123 확산어디서나 하스켈을 멋진 명령형 언어로 작성하십시오.

fac 0 = putStrLn "0! = 1" >> return 1 
fac n = do 
    x <- fac (n - 1) 
    let r = x * n 
    putStrLn $ show n ++ "! = " ++ show r 
    return r 

둘째 unsafePerformIO 및 그 유도체 (예를 들면 Debug.Trace)를 사용한다. 발과 디버깅 목적으로 촬영할 때 유용합니다.

세 번째 : 코드에서 I/O 및 계산을 혼합하는 대신 중간 결과가 포함 된 [잠재적으로 무한한] 데이터 구조를 순수 함수로 지연 생성하고 별도로 소비합니다. 예를 들어, 계승의 무한한 목록은 다음과 같이 쓸 수있다 :

facs = scanl (*) 1 [1..] 

그리고 위의 예에서 fac 10를 호출과 동일한 결과를 산출하기 위해 다음과 같이 소비 : 몇 가지 더 많은 옵션이있다

forM_ (take 11 $ zip [0..] facs) $ \(i, x) -> 
    putStrLn $ show i ++ "! = " ++ show x 
+8

이러한 옵션 중 세 번째가 가장 좋습니다. – dave4420

2

그 rkhayrov하지 않았다 cover in their answer

그냥 디버그 정보를 원한다면 Debug.Trace's trace function을 사용해보십시오.

import Debug.Trace 

fact :: (Ord a, Num a) => a -> a 
fact n | n > 1 = traceShow n $ n * fact (n-1) 
     | otherwise = traceShow n $ 1 

버그 사냥 이외의 용도로는 사용하지 않는 것이 좋습니다. 확실히 생산 코드로 들어가서는 안됩니다.

작업하는 동안 정보를 기록하려면 Writer Monad을 사용해보십시오.

import Control.Monad.Writer.Lazy 
import Control.Applicative ((<$>)) 

fact :: (Ord a, Num a) => a -> Writer [String] a 
fact n = do 
    tell $ [show n] 
    if n > 1 
    then 
     (n*) <$> fact (n-1) 
    else 
     return 1 

또한보다 일반적인 가서 MonadWriter typeclass를 사용할 수 있습니다.

관련 문제