Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>One way to avoid the use of <code>show</code> is this one</p> <pre><code>reverseInt :: Integer -&gt; Integer reverseInt n = aux (n,0) where aux (0,y) = y aux (x,y) = let (x',y') = x `quotRem` 10 in aux (x',10*y+y') </code></pre> <p>and it works with negative numbers too.</p> <h2>EDIT2:</h2> <p>As pointed out in the comments the aux function can be a bit optimized omitting the tuple, which can prevent the compiler from evaluating to whnf (weak head normal form), i.e. if the compiler sees an expression it evaluates it as little as necessary, until it sees the first constructor. And in case of aux it is the tuple constructor <code>(,)</code>. A good feeling for whnf can be achieved with ghci + <code>:sprint</code>, see simon marlow's book (<a href="http://chimera.labs.oreilly.com/books/1230000000929/ch02.html" rel="noreferrer">http://chimera.labs.oreilly.com/books/1230000000929/ch02.html</a>).</p> <pre><code>reverseInt :: Int -&gt; Int reverseInt n = aux n 0 where aux 0 y = y aux x y = let (x',y') = x `quotRem` 10 in aux x' (10*y+y') </code></pre> <p>As pointed out by @FrerichRaabe this does the required task, but understanding it is a bit more tricky than - <code>read . reverse . show</code>, I admit that. So I'll explain in an example what <code>aux</code> does: </p> <pre><code>aux 1234 0 =&gt; 1234 `quotRem` 10 =&gt; (123,4) =&gt; x'= 123, y'= 4 =&gt; aux 123 (0*10+4) =&gt; aux 123 4 aux 123 4 =&gt; 123 `quotRem` 10 =&gt; (12,3) =&gt; x'= 12, y'= 3 =&gt; aux 12 (4*10+3) =&gt; aux 12 43 aux 12 43 =&gt; 12 `quotRem` 10 =&gt; (1,2) =&gt; x'= 1, y'= 2 =&gt; aux 1 (43*10+2) =&gt; aux 1 432 aux 1 432 =&gt; 1 `quotRem` 10 =&gt; (0,1) =&gt; x'= 0, y'= 1 =&gt; aux 0 (432*10+1) =&gt; aux 0 4321 aux 0 4321 =&gt; 4321 </code></pre> <h2>EDIT:</h2> <p>I decided whether my assumptions of including <code>show</code> is a bad idea were justified.</p> <p><strong>short version</strong> yes!</p> <p><strong>long version</strong> I put all versions in one file and added a strict version of my approach to see, if the non strict part in the accumulator mattered (as it turned out: not really). What mattered was the choice between <code>Int</code> (which is Int64) on my machine and <code>Integer</code> in my Versions</p> <ul> <li>the Int version took about 200 ns </li> <li>Integer version ---- " ----- 600 ns</li> </ul> <p>the other versions involving <code>show</code> and <code>read</code> took a bit longer, but all of them were around 6000 ns - which is a factor of 30 resp. 10 compared to my version. For further information you may want to look at the report produced by the <code>criterion</code> library (thank you Bryan O'Sullivan!!), save the files below and type in your shell.</p> <pre><code>$ ghc -O --make benchmarks.hs $ ./benchmarks -o Report.html </code></pre> <p><strong>RevInt.hs</strong></p> <pre><code>{-# LANGUAGE BangPatterns #-} module RevInt where epsilon_fast :: Int-&gt; Int epsilon_fast n = aux n 0 where aux :: Int -&gt; Int -&gt; Int aux 0 !y = y aux x !y = let (x',y') = x `quotRem` 10 in aux x' (10*y+y') epsilon_Integer :: Integer -&gt; Integer epsilon_Integer n = aux (n,0) where aux (0,y) = y aux (x,y) = let (x',y') = x `quotRem` 10 in aux (x',10*y+y') epsilon_rInt :: Int-&gt; Int epsilon_rInt n = aux (n,0) where aux (0,y) = y aux (x,y) = let (x',y') = x `quotRem` 10 in aux (x',10*y+y') epsilon_Integer' :: Integer -&gt; Integer epsilon_Integer' n = aux (n,0) where aux (0,y) = y aux (x,y) = let (x',y') = x `quotRem` 10 !z = 10*y+y' in aux (x',z) epsilon_rInt' :: Int-&gt; Int epsilon_rInt' n = aux (n,0) where aux (0,y) = y aux (x,y) = let (x',y') = x `quotRem` 10 !z = 10*y+y' in aux (x',z) fRaabe_Integer :: Integer -&gt; Integer fRaabe_Integer x | x &lt; 0 = 0 - (read . reverse . tail . show $ x) | otherwise = read . reverse . show $ x fRaabe_Int :: Int -&gt; Int fRaabe_Int x | x &lt; 0 = 0 - (read . reverse . tail . show $ x) | otherwise = read . reverse . show $ x zeta_Int :: Int -&gt; Int zeta_Int x = (*) (signum x) . read . reverse . show . abs $ x zeta_Integer :: Integer -&gt; Integer zeta_Integer x = (*) (signum x) . read . reverse . show . abs $ x </code></pre> <p><strong>benchmarks.hs</strong></p> <pre><code>import Criterion.Main import RevInt main :: IO () main = defaultMain [bgroup "epsilon_fast" [ bench "123456789" $ whnf epsilon_fast 123456789 , bench "987654321" $ whnf epsilon_fast 987654321 ] ,bgroup "epsilon_Integer" [ bench "123456789" $ whnf epsilon_Integer 123456789 , bench "987654321" $ whnf epsilon_Integer 987654321 ] ,bgroup "epsilon_rInt" [ bench "123456789" $ whnf epsilon_rInt 123456789 , bench "987654321" $ whnf epsilon_rInt 987654321 ] ,bgroup "epsilon_Integer'"[ bench "123456789" $ whnf epsilon_Integer' 123456789 , bench "987654321" $ whnf epsilon_Integer' 987654321 ] ,bgroup "epsilon_rInt'" [ bench "123456789" $ whnf epsilon_rInt' 123456789 , bench "987654321" $ whnf epsilon_rInt' 987654321 ] ,bgroup "fRaabe_Int" [ bench "123456789" $ whnf fRaabe_Int 123456789 , bench "987654321" $ whnf fRaabe_Int 987654321 ] ,bgroup "fRaabe_Integer" [ bench "123456789" $ whnf fRaabe_Integer 123456789 , bench "987654321" $ whnf fRaabe_Integer 987654321 ] ,bgroup "zeta_Int" [ bench "123456789" $ whnf zeta_Int 123456789 , bench "987654321" $ whnf zeta_Int 987654321 ] ,bgroup "zeta_Integer" [ bench "123456789" $ whnf zeta_Integer 123456789 , bench "987654321" $ whnf zeta_Integer 987654321 ]] </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload