Creating output in the current haskell program

Based on the (SWI) Prolog, I find it very difficult to get Haskell to produce results on the fly.

The simplest example, I would like Haskell to print something at each iteration:

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

Or I would like to get out of a program that never stops ...

 -- A possible halt statement... -- find_primes l 100 = l find_primes ln = if ( is_prime ln ) then find_primes nn s else find_primes ls 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 tn else False where r = n mod h 

Prelude> find_primes [] 2

+4
source share
2 answers

You have three options:

First: distribute IO everywhere and write in Haskell, as in a bizarre imperative language.

 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 

Second: use unsafePerformIO and its derivatives (e.g. Debug.Trace ). Useful for shooting legs and debugging purposes.

Thirdly: instead of mixing I / O and computing in the code, it is lazy to generate a [potentially infinite] data structure containing intermediate results in a pure function and consume it separately. For example, an endless list of factorials can be written as:

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

And it is consumed as follows to get the same result as when calling fac 10 in the above example:

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

There are several more options that rkhayrov is not a cover in his answer

If you need only debugging information, consider using the Debug.Trace 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 

I cannot recommend using this for more than hunting for bugs. This definitely should not go into production code.

If you want to record information while you work, consider using 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 

You can also go more general and use the MonadWriter class.

+2
source

Source: https://habr.com/ru/post/1369278/


All Articles