玩 xmobar,当我看到这个
, 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
]
我没有想太多就说“哦,我可以把那个
Run
拉出来”并写道
, commands = Run <$> [Weather {- ... -}
, Network {- ... -}
, Network {- ... -}
, Cpu {- ... -}
, Memory {- ... -}
, Swap {- ... -}
, Com {- ... -}
, Date {- ... -}
, HelloWorld
]
但这显然不起作用,因为例如
Data
、HelloWorld
和 Weather
是不同的类型。
但是有些可以放在一个列表中,例如这种类型检查
foo = [ Weather undefined undefined undefined
, Cpu undefined undefined
, DiskU undefined undefined undefined
, Memory undefined undefined ]
但这不是
foo = [ Weather undefined undefined undefined
, Cpu undefined undefined
, DiskU undefined undefined undefined
, Date undefined undefined undefined -- because of this
, Memory undefined undefined ]
Date
是一个实际的 data
类型,但是其他的是什么?
Weather
,除了评论和
Weather
的名字之外,我什至看不到单个词
module
。
那么
Weather
是什么?我在哪里可以看到它的定义?
事实上,
Weather
和Memory
可以放在同一个列表中,这让我想到了我几乎没有经验的存在类型。然而,从那个维基页面,我看到这个
data Worker x y = forall b. Buffer b => Worker {buffer :: b, input :: x, output :: y}
是定义
Worker
的方法,它可以容纳任何类型的 buffer
,只要该类型实现 Buffer
。
现在,鉴于上面第一个
foo
的类型为 [Monitors]
类型,我猜 Monitors
正在扮演 Worker
的角色,即存在类型,而 Weather
、Memory
等则是实现任何接口(对应于 Buffer
)的类型的值构造函数都会限制存在类型 Monitors
可以包装的类型。但是 Date
没有实现该接口,所以它不能与其他接口一起使用。
是这样吗
但是如果是这样的话...那么
Weather
、Memory
和其他人的定义及其接口的实现在哪里?
不要只搜索 Weather.hs 文件,而是在整个存储库中搜索。您会发现
Monitors.hs
功能 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
-- ...
它不是一个存在类型,只是一个普通的Haskell代数数据类型,因此没有“接口”来支持。它们可以一起列在一个列表中,因为它们都是同一类型 (
Monitors
)。
有一个密切相关的存在类型
Runnable
,在Runnable.hs
中定义,如
data Runnable = forall r . (Exec r, Read r, Show r) => Run r
这是一种存在类型,允许
Run $ Date ...
与其他监视器(如 Run $ Memory ...
)位于同一列表中,即使 Date
类型和 Monitors
类型不直接相关。它们都满足 Runnable
约束,并且 Runnable
包装器隐藏了所有其他细节,以便可以统一对待它们。