0votos

Dar formato a un registro de tiempos tipo StopWatch en Haskell

por josejuan hace 3 meses

En lugar de formatear directamente, se convierte a una estructura en árbol que es más útil, por ejemplo para formatear.

StopWatch es una conocida clase de .Net y Java que permite medir los tiempos de ejecución de nuestro código. Se pide dar formato a los registros realizados por este tipo de trazas.

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
69
70
71
72
73
74
75
{-# LANGUAGE LambdaCase, RecordWildCards #-} 
import Control.Arrow (first) 
 
-- Nos dicen que hay una serie de registros de eventos quizás anidados 
-- con una etiqueta, un instante de inicio y un instante de fin. Un registro de 
-- dichos eventos podría ser: 
data Event = Start ℤ 𝐒 | Stop ℤ deriving Show 
 
-- Y del que un buen ejemplo podría ser el que indican en el enunciado: 
good = [ Start 10 "Start process" 
       , Start 15 "Reading configuration" 
       , Stop  21 
       , Start 24 "Processing data" 
       , Start 24 "Preprocessing factors" 
       , Stop  26 
       , Start 28 "Computing result" 
       , Stop  29 
       , Stop  31 
       , Start 32 "Closing resources" 
       , Stop  33 
       , Stop  33 
       , Start 33 "Exiting" 
       , Stop  33 
 
-- Y del que un mal ejemplo podría ser eliminar una de las marcas de `stop`: 
bad = take 8 good ⧺ drop 9 good 
 
-- Lo más conveniente no es formatear directamente la salida sino convertir la entrada de 
-- eventos a alguna estructura más útil (por ejemplo si posteriormente queremos analizarla) 
-- como un árbol ya que los eventos pueden estar anidados: 
data TTime = TTime { name :: 𝐒, start :: ℤ, end :: ℤ, children :: [TTime] } deriving Show 
 
-- Así, realmente lo que hacemos es convertir con coste líneal (en una sóla pasada) la 
-- secuencia de eventos a un árbol. Como podrían estar mal anidados usamos la mónada `Either`: 
toTTime :: [Event] → 𝐄 𝐒 ([TTime], [Event]) 
toTTime (Start a n: xs) = toTTime xs ↪ (λcase 
                            (cs, Stop b: ys) → ((TTime n a b cs:) `first`) ↥ toTTime ys 
                            _                → 𝐿 "bad nested times") 
toTTime             xs  = 𝑅 ([], xs) 
 
-- Y ya está. Ahora podríamos analizar el árbol (ej. obtener el coste interno más grande) o, 
-- como nos piden, formatearlo, por ejemplo: 
formatTTime :: TTime → [𝐒] 
formatTTime TTime {…} = ("|- " ⧺ name ⧺ " (" ⧺ show (end - start) ⧺ " mS)"): 
                        concatMap (map ("    "⧺) ∘ formatTTime) children 
 
-- Y ya está. Por comodidad, podemos escribir un helper que controle un posible error e 
-- imprima por la consola el resultado (éxito o error): 
formatAndPrint :: [Event] → IO () 
formatAndPrint xs = ↱_putStrLn $ either (:[]) id $ (concatMap formatTTime ∘ fst) ↥ toTTime xs 
 
 
 
 
 
 
{- Las salidas al ejecutar con `good` o `bad` son: 
 
 
> formatAndPrint good 
|- Start process (23 mS) 
    |- Reading configuration (6 mS) 
    |- Processing data (7 mS) 
        |- Preprocessing factors (2 mS) 
        |- Computing result (1 mS) 
    |- Closing resources (1 mS) 
|- Exiting (0 mS) 
 
 
> formatAndPrint bad 
bad nested times 
 
 
-} 

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.