一种越频繁出现的模式,引入的类型安全就越多,newtype是将一个值(或多个值)投影到newtype包装器,执行一些操作,然后收回投影。一个普遍存在的例子是Sum和Product幺半群:
λ x + y = getSum $ Sum x `mappend` Sum y
λ 1 + 2
3
我想可能withSum会withSum2自动为每个newtype. 或者也许Identity可以创建一个参数化,用于ApplicativeDo. 或者,也许还有其他一些我想不到的方法。
我想知道这方面是否有一些现有技术或理论。
PS 我不满意coerce,有两个原因:
安全 我认为这不是很安全。在被指出它实际上是安全的之后,我尝试了一些事情并且我无法做任何有害的事情,因为当存在歧义时它需要类型注释。例如:
λ newtype F = F Int deriving Show λ newtype G = G Int deriving Show λ coerce . (mappend (1 :: Sum Int)) . coerce $ F 1 :: G G 2 λ coerce . (mappend (1 :: Product Int)) . coerce $ F 1 :: G G 1 λ coerce . (mappend 1) . coerce $ F 1 :: G ... • Couldn't match representation of type ‘a0’ with that of ‘Int’ arising from a use of ‘coerce’ ...但我仍然不欢迎
coerce,因为一旦习惯了伸手去拿,撕下安全标签并射杀某人太容易了。想象一下,在加密应用程序中,有两个值:x :: Prime Int和x' :: Sum Int。我宁愿打字getPrime,getSum每次我使用它们时,也不愿coerce做任何事情,并且有一天会犯一个灾难性的错误。关于某些操作的速记,有用性
coerce并没有带来太多好处。我的帖子的主要示例,我在这里重复:λ getSum $ Sum 1 `mappend` Sum 2 3——变成了类似这个尖刺怪物的东西:
λ coerce $ mappend @(Sum Integer) (coerce 1) (coerce 2) :: Integer 3——这几乎没有任何好处。