一种越频繁出现的模式,引入的类型安全就越多,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
——这几乎没有任何好处。