假设我有以下代码
type IsTall = Bool
type IsAlive = Bool
is_short_alive_person is_tall is_alive = (not is_tall) && is_alive
说,稍后,我有以下
a :: IsAlive
a = False
b :: IsTall
b = True
并调用以下命令,以错误的方式获取两个参数:
is_short_alive_person a b
不幸的是,这成功编译,并且在运行时找到了高个子死人而不是短命人。
我希望上面的示例不要编译。
我的第一次尝试是:
newtype IsAlive = IsAlive Bool
newtype IsTall = IsTall Bool
但是我不能做类似的事情。
switch_height :: IsTall -> IsTall
switch_height h = not h
Asnot没有在IsTalls 上定义,只有Bools。
我可以一直明确地提取Bools ,但这在很大程度上违背了目的。
基本上,我希望IsTalls 与其他IsTalls 交互,就像它们是Bools 一样,只是它们不会在没有显式强制转换的情况下与Bools 和s 交互。IsAlive
实现这一目标的最佳方法是什么。
ps 我想我已经通过在 GHC 中的数字实现了这一点:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype UserID = UserID Int deriving (Eq, Ord, Num)
newtype GroupID = GroupID Int deriving (Eq, Ord, Num)
(即 UserID 和 GroupID 不应该交互)
但我似乎无法用Bools 做到这一点(派生 Bool 不起作用)。我什至不确定以上是最好的方法。