有没有一个“单位”?班级?有用吗?
是否有一个类用于具有单个单位值的类型(不确定这里的术语是否正确),即具有一些预定义值的类型?
class Unit a where
unit :: a
instance Unit () where
unit = ()
instance Unit (Maybe a) where
unit = Nothing
...对于所有 Monoids、MonadPlus 等。
我想该类的另一个名称可能是 Default
。这对我来说最近两次很有用。
可能没有令人信服的例子:
extract :: (Unit r)=> Reader r a -> a
extract r = runReader r unit
这存在吗?其他人认为这可能有用吗?
Is there a class for types having a single unit value (not sure of the correct terminology here) i.e. types with some pre-defined value?
class Unit a where
unit :: a
instance Unit () where
unit = ()
instance Unit (Maybe a) where
unit = Nothing
...for all Monoids, MonadPlus, etc.
I suppose another name for the class might be Default
. This would have been useful twice recently now for me.
Probably unconvincing example:
extract :: (Unit r)=> Reader r a -> a
extract r = runReader r unit
Does this exist? Do others think it might be useful?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,它可能会有用。事实上,它的所有稍微不兼容的版本都是有用的!这有点问题。
甚至不清楚这样的类意味着什么,这使得实际使用变得困难,因为不可避免地你会遇到有多种默认值选择的类型,并且如果不立即清楚哪个默认值一旦实例提供了,您几乎就失去了首先拥有该类的所有好处。
几个例子:
对于
Monoid
实例,您显然希望恒等元素是默认值。但现在您又回到了许多类型具有两个或更多合理Monoid
实例的问题。默认的Integer
是0还是1?对于Monoid
,标准库使用newtype
包装器,但这些包装器很笨拙,并且很难使用包装的类型 - 使用Monoid
它工作正常,因为您可以访问mconcat
等,但您无法仅使用默认值做任何有趣的事情。对于具有“空”值的仿函子类型,这给出了明显的默认值。这就是
MonadPlus
和Alternative
正在做的事情......并且也与Monoid
重叠,如果我没记错的话,至少有一种类型三个实例并不相同。当有多个选择时,你会选择哪一个?考虑列表:您可以盲目地附加它们,给出任意Monoid
,并以空列表作为标识;但对于Monoids
列表,您还可以zipWith mappend
,给出一个以repeat mempty
为标识的提升的monoid。 都有类似的Monoid
实例,但并不总是两者都有 - 因此,无论您选择哪个列表,您都会在概念上与其他一些Functor
不一致!对于像
()
这样的单位类型,选择默认值并不难!但是枚举呢?选择第一个构造函数有意义吗?有时,但并非总是如此。使用该类的人如何知道?有界
怎么样?如果以上都不适用,您可以使用minBound
。但上述某些类型也可能是Bounded
,因此如果它们的默认值不是最小值,您就会感到困惑。基本上,有足够的重叠,似乎有意义......但实际上,您在这里至少想到了三种不同的类型类,并且尝试统一它们可能没有那么有帮助乍一看似乎是这样。
如果您可以更好地确定事情并为“默认”值提供清晰、一致的语义解释,而无需只需重新发明
Monoid
或另一个现有类,这样类型类很容易使用,无需停下来思考选择什么“默认”,太棒了!但我不会对它发挥作用抱有希望。也就是说,任何标准类型类都没有涵盖的一个明显合理的情况是像
()
这样的单例。大多数时候,这些并不是很有用——原因很明显!——这可能就是没有这样一个类的原因。然而,这样的类非常有用的一个地方是,当您正在做一些涉及类型级别的恶作剧时,因为这样的类型在类型和术语级别上都表示单个值 - 所以此类类型的类可以让您自由地操作类型级值,然后想出与之相关的术语,这样您就可以将其传递给其他一些函数,例如,可以根据它选择一个类型类实例。因此,我在我永远不完整的类型黑客库中有一个类似的类,例如:不过,我怀疑这样的类在任何其他上下文中都非常有用。
Yes, it would probably be useful. In fact, all of the slightly incompatible versions of it would be useful! Which is kinda the problem.
It's not clear what such a class would even mean, which makes it hard to actually use, because inevitably you'll hit types where there are multiple choices of a default value, and if it's not immediately clear which one the instance provides, you pretty much lose all benefit of having the class in the first place.
A few examples:
For
Monoid
instances, you'd obviously expect the identity element to be the default. But now you're back to the problem of so many types having two or more sensibleMonoid
instances. Is the defaultInteger
0 or 1? ForMonoid
, the standard library usesnewtype
wrappers, but those are clumsy and make it difficult to work with the wrapped types--withMonoid
it works okay because you get access tomconcat
and such, but you can't do anything interesting with just a default value.For
Functor
-like types with an "empty" value, that gives an obvious default. This is whatMonadPlus
andAlternative
are doing... and also overlaps withMonoid
, and if memory serves me there's at least one type where those three instances aren't identical. Which do you pick, when there's more than one choice? Consider lists: You can blindly append them, giving an arbitraryMonoid
, with the empty list as identity; but for lists ofMonoids
you can alsozipWith mappend
, giving a lifted monoid withrepeat mempty
as the identity. Many functors have analogousMonoid
instances, but not always both--so whichever you pick for lists, you'll be conceptually inconsistent with some otherFunctor
!For unit types like
()
, it's not hard to pick a default! But what about enumerations? Does it make sense to pick the first constructor? Sometimes, but not always. How will people using the class know?What about
Bounded
? If none of the above applies, you could useminBound
. But some of the above types could beBounded
as well, so you'll confuse matters if their default isn't their minimum value.Basically, there's just enough overlap that it seems to make sense... but really, you've got at least three different type classes in mind here, and trying to unify them is probably not as helpful as it seems at first.
If you can pin things down a little better and give a clear, consistent semantic interpretation of a "default" value, without just reinventing
Monoid
or another existing class, such that the type class is easy to use without having to stop and think about what "default" gets chosen, great! But I wouldn't get my hopes up on making it work.That said, the one obviously sensible case that's not covered by any standard type class is singletons like
()
. Most of the time these aren't terribly useful--for obvious reasons!--which is probably why there isn't such a class. One place where such a class is extremely useful, though, is when you're doing something involving type-level shenanigans, because such a type represents a single value at both the type and term level--so a class for such types lets you manipulate type-level values freely, then conjure up the term that goes with it, so you can pass it to some other function that might, e.g., select a type class instance based on it. For that reason, I have a class along those lines in my perpetually-incomplete type-hackery library, e.g.:I doubt such a class is very useful in any other context, though.
您正在寻找某种
Default
类型类。虽然“默认”的语义应该是什么是有争议的(我建议您接受 CA McCanns 的回答,因为他在那里提出了宝贵的意见),您可以从一个相当常用的名为Default
的包中获取一个Default
类。 a href="http://hackage.haskell.org/package/data-default-0.3.0" rel="nofollow">data-default
。班级是:
You are looking for some sort of
Default
type class. While the semantics of what a "default" should be is debatable (and I suggest you accept C.A. McCanns answer for his valuable comments there), you can get aDefault
class from a fairly commonly used package calleddata-default
.The class is:
如果您想避免使用新类,可以根据 Enum 类定义单位:
或者使用 Bounded 类可能更好:
这两者都会产生单位类型的预期结果(并且很可能适用于任何其他单个构造函数类型) :
与 data-default 类(在另一个答案中提到)相比,缺点是实例较少,特别是没有为 [a] 返回 [] 的实例。此外,结果也不是您所期望的某种类型的结果,特别是如果您使用 minBound:
If you want to avoid a new class, you can define unit in terms of the Enum class:
Or maybe better with the Bounded class:
Both of these produce the expected result for the unit type (and most likely for any other single constructor type):
The drawbacks compared to the data-default class (mentioned in another answer) is that there are fewer instances, particularly no instance that returns [] for [a]. Also the result is not what you might expect from some type, especially if you use minBound: