Playing around with xmobar, when I saw this
, commands = [ Run $ Weather "EGPH" ["-t","<station>: <tempC>C",
"-L","18","-H","25",
"--normal","green",
"--high","red",
"--low","lightblue"] 36000
, Run $ Network "eth0" ["-L","0","-H","32",
"--normal","green","--high","red"] 10
, Run $ Network "eth1" ["-L","0","-H","32",
"--normal","green","--high","red"] 10
, Run $ Cpu ["-L","3","-H","50",
"--normal","green","--high","red"] 10
, Run $ Memory ["-t","Mem: <usedratio>%"] 10
, Run $ Swap [] 10
, Run $ Com "uname" ["-s","-r"] "" 36000
, Run $ Date "%a %b %_d %Y %H:%M:%S" "date" 10
, Run HelloWorld
]
I without thinking too much I said "oh, I can pull that Run
out" and wrote
, commands = Run <$> [Weather {- ... -}
, Network {- ... -}
, Network {- ... -}
, Cpu {- ... -}
, Memory {- ... -}
, Swap {- ... -}
, Com {- ... -}
, Date {- ... -}
, HelloWorld
]
but this obviously doesn't work, because for instance Data
, HelloWorld
and Weather
are different types.
But some can go together within a list, e.g. this type checks
foo = [ Weather undefined undefined undefined
, Cpu undefined undefined
, DiskU undefined undefined undefined
, Memory undefined undefined ]
but this doesn't
foo = [ Weather undefined undefined undefined
, Cpu undefined undefined
, DiskU undefined undefined undefined
, Date undefined undefined undefined -- because of this
, Memory undefined undefined ]
Now I see that Date
is an actual data
type, but what are the others?
If I open Weather
I don't even see the single word Weather
other than in a comment and in the name of the module
.
So what is Weather
? And where do I see its definition?
The fact that Weather
and, say, Memory
can go in the same list makes me think of existential types of which I have little experience. However, from that wiki page, I see that this
data Worker x y = forall b. Buffer b => Worker {buffer :: b, input :: x, output :: y}
is the way of defining a Worker
that can hold a buffer
of whatever type, as long as that type implements Buffer
.
Now, given that the type of the first foo
above has type [Monitors]
, I guess that Monitors
is playing the role of Worker
, the existential type, and Weather
, Memory
and others are value constructors of types that implement whatever interface (corresponding to Buffer
) is constraining the the type that the existential type Monitors
can wrap. But Date
doesn't implement that interface, so it can't go with the others.
Is it like this?
But if that's the case... then where are Weather
's, Memory
's and others' definitions, togheter with their implementation of the interface?
Instead of searching in just the Weather.hs file, search in the whole repository. You will find Monitors.hs
features a definition of Weather
:
data Monitors = Network Interface Args Rate
-- ...
| DiskU DiskSpec Args Rate
-- ...
| Memory Args Rate
| Swap Args Rate
| Cpu Args Rate
-- ...
#ifdef WEATHER
| Weather Station Args Rate
| WeatherX Station SkyConditions Args Rate
#endif
-- ...
It is not an existential type, just an ordinary Haskell algebraic data type, so there is no "interface" to support. They can go in a list together because they are all of the same type (Monitors
).
You could also find this out by reading the Haddock documentation for xmobar instead of poring through the source. It's nicely indexed and cross-linked so you can find the definitions you're looking for, and links to the source if you want to see more details.
There is a closely related existential type Runnable
, defined in Runnable.hs
, as
data Runnable = forall r . (Exec r, Read r, Show r) => Run r
This is the existential type that allows Run $ Date ...
to be in the same list as the other monitors like Run $ Memory ...
, even though the Date
type and Monitors
type are not directly related. They each satisfy the Runnable
constraints, and the Runnable
wrapper hides all their other details so they can be treated uniformly.