是否有类似`fromNewtype之类的操作的简写形式. F . toNewtype`? [英] Is there a shorthand for operations like `fromNewtype . f . toNewtype`?
问题描述
通过newtype
引入类型安全性越高的模式越多地出现,那就是将值(或多个值)投射到newtype
包装器中,执行一些操作,然后缩回投影.一个普遍存在的例子是Sum
和Product
mono半群的例子:
A pattern that presents itself the more often the more type safety is being introduced via newtype
is to project a value (or several values) to a newtype
wrapper, do some operations, and then retract the projection. An ubiquitous example is that of Sum
and Product
monoids:
λ x + y = getSum $ Sum x `mappend` Sum y
λ 1 + 2
3
我想像withSum
,withSum2
等功能的集合可能会针对每个newtype
自动推出.或者,可能会创建参数化的Identity
,以与ApplicativeDo
一起使用.也许还有其他我想不到的方法.
I imagine a collection of functions like withSum
, withSum2
, and so on, may be automagically rolled out for each newtype
. Or maybe a parametrized Identity
may be created, for use with ApplicativeDo
. Or maybe there are some other approaches that I could not think of.
我想知道是否存在一些现有技术或理论.
I wonder if there is some prior art or theory around this.
PS 我对coerce
不满意,有两个原因:
P.S. I am unhappy with coerce
, for two reasons:
-
安全 我以为不是很安全.在指出它实际上是安全的之后,我 尝试了几件事,但我却无济于事,因为它需要类型注释 当有歧义的可能性时.例如:
safety I thought it is not very safe. After being pointed that it is actually safe, I tried a few things and I could not do anything harmful, because it requires a type annotation when there is a possibility of ambiguity. For example:
λ 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
一切都要好一天
犯了灾难性的错误.
But I would still not welcome coerce
, because it is far too easy to strip a safety label and
shoot someone, once the reaching for it becomes habitual. Imagine that, in a cryptographic
application, there are two values: x :: Prime Int
and x' :: Sum Int
. I would much rather
type getPrime
and getSum
every time I use them, than coerce
everything and have one day
made a catastrophic mistake.
有用性 coerce
对于速记的作用不大
某些操作.我的帖子的主要示例,我在这里重复:
usefulness coerce
does not bring much to the table regarding a shorthand for
certain operations. The leading example of my post, that I repeat here:
λ getSum $ Sum 1 `mappend` Sum 2
3
—变成了与这个尖刺怪兽相似的东西:
— Turns into something along the lines of this spiked monster:
λ coerce $ mappend @(Sum Integer) (coerce 1) (coerce 2) :: Integer
3
—几乎没有任何好处.
— Which is hardly of any benfit.
推荐答案
Your "spiked monster" example is better handled by putting the summands into a list and using the ala
function available here, which has type:
ala :: (Coercible a b, Coercible a' b')
=> (a -> b)
-> ((a -> b) -> c -> b')
-> c
-> a'
其中
-
a
是未包装的基本类型. -
b
是包装a
的新类型. -
a -> b
是新类型的构造函数. -
((a -> b) -> c -> b')
是一个函数,它知道如何包装基本类型a
的值,知道如何处理类型c
的值(几乎总是a
s的容器)并返回包装的结果b'
.实际上,此功能几乎总是foldMap
. -
a'
未包装的最终结果.展开由ala
本身处理.
a
is the unwrapped base type.b
is the newtype that wrapsa
.a -> b
is the newtype constructor.((a -> b) -> c -> b')
is a function that, knowing how to wrap values of the base typea
, knows how to process a value of typec
(almost always a container ofa
s) and return a wrapped resultb'
. In practice this function is almost alwaysfoldMap
.a'
the unwrapped final result. The unwrapping is handled byala
itself.
在您的情况下,它将类似于:
in your case, it would be something like:
ala Sum foldMap [1,2::Integer]
可以通过coerce
以外的其他方式来实现
"ala"功能,例如,镜头.
"ala" functions can be implemented through means other than coerce
, for example using generics to handle the unwrapping, or even lenses.
这篇关于是否有类似`fromNewtype之类的操作的简写形式. F . toNewtype`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!