Let it (binary) snow!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import Control.Monad
import Data.Time.Clock
import Data.Time.LocalTime

import Data.BNum            -- http://lpaste.net/108426

{--

A solution to today's exercise posted at http://lpaste.net/108420

So, now we can count by unary numbers and also by binary numbers. We are living
the high life! What more could we ask for?

Well, mo' time, of course!

Given the current input UTC time, output, however you see fit, the current
time as a binary string of 'digits.' ... whatever 'digits' mean to you, including,
possibly, the meaning of the word 'BlinkenLights.'

https://en.wikipedia.org/wiki/Blinkenlights

*Main Data.Time.Clock Data.Time.LocalTime> getCurrentTime >>= 
                                           return . utcToLocalTime utc
2014-07-30 12:06:55.64355

 --}

blinkenLights :: UTCTime -> [String]
blinkenLights utcTime = 
   let localDate = utcToLocalTime utc utcTime
       TimeOfDay hr min sec = localTimeOfDay localDate
       hms = map (flip divMod 10) [toInteger hr, toInteger min, floor (sec + 0.5)]
       bbs = join (map (\(a, b) -> [fromInteger a, fromInteger b]) hms)
       snowfall = map (map flakes . bits) (transpose bbs)
       flakes '1' = '*'
       flakes '0' = ' '
   in  snowfall

letItSnow :: IO ()
letItSnow = getCurrentTime >>= return . blinkenLights >>= mapM_ putStrLn

{--

Ooh! My binary clock, right on my desktop!

*Main> letItSnow
***  *
 ***  
 *    
     *
*Main> letItSnow
*** * 
 ***  
 *    
*Main> letItSnow
*** * 
 ***  
 *    
*Main> letItSnow
*** **
 ***  
 *    
*Main> letItSnow
*** * 
 *** *
 *    

 --}
32:18: Warning: Use section
Found:
(flip divMod 10)
Why not:
(`divMod` 10)
40:13: Warning: Use liftM
Found:
getCurrentTime >>= return . blinkenLights
Why not:
liftM blinkenLights getCurrentTime