我想有一个类型类,告诉我各种类型有多大。
data Cardinality = Finite Natural | Infinite
class Sized a where cardinality :: Cardinality
编写实例非常简单;例如:
instance Sized Void where cardinality = Finite 0
instance Sized () where cardinality = Finite 1
instance Sized Bool where cardinality = Finite 2
instance Sized a => Sized [a] where
cardinality = case cardinality @a of
Finite 0 -> Finite 1
_ -> Infinite
data X = X Y
data Y = Y X X
instance Sized X where cardinality = Finite 1
instance Sized Y where cardinality = Finite 1
事实上,它是如此简单,感觉它应该是自动化的。也许通用编程会有所帮助?
class GSized f where gcardinality :: Cardinality
class Sized a where
cardinality :: Cardinality
default cardinality :: (Generic a, GSized (Rep a)) => Cardinality
cardinality = gcardinality @(Rep a)
大多数实例都非常简单:
instance GSized V1 where gcardinality = Finite 0
instance GSized U1 where gcardinality = Finite 1
instance GSized f => GSized (M1 i c f) where gcardinality = gcardinality @f
instance (GSized f, GSized g) => GSized (f :+: g) where
gcardinality = case (gcardinality @f, gcardinality @g) of
(Finite n, Finite n') -> Finite (n+n')
_ -> Infinite
instance (GSized f, GSized g) => GSized (f :*: g) where
gcardinality = case (gcardinality @f, gcardinality @g) of
(Finite 0, _) -> Finite 0
(_, Finite 0) -> Finite 0
(Finite n, Finite n') -> Finite (n*n')
_ -> Infinite
但是后来我被卡住了。对于单个字段来说,简单明了的事情肯定行不通:
instance Sized c => GSized (K1 i c) where
gcardinality = cardinality @c
对于递归类型,这是一个非常简单的无限循环。我已经尝试了各种方法来丰富这里涉及的两个班级。
cardinality
和gcardinality
概括为函数,这样我就可以假设我已经知道递归出现的大小。然后在K1
实例中,我可以问:如果所有递归实例都是无人居住的,那么您会有多大?如果您的所有递归实例都有一个居住者呢?等等
x=abx
。x=abx
的预期含义是类型x
具有根本不涉及递归的a
居民,以及可以与递归调用配对的b
值。(我们可以定义x*x=x
,而不会丢失任何感兴趣的内容。)然后像x=n0x
这样的方程对应于枚举,x=0x
对应于平凡的1元素递归类型,x=abx
是无限的
Generic1
而不是Generic
所有这些最终都不起作用。似乎有三种核心、难题/故障模式:
K1
定义中的一个循环,或者对于递归类型它可以正常工作,但是对于相互递归的类型它会失败
K1
既用于递归引用,也用于普通字段,而且似乎没有一种简单的方法来区分它们
Finite 0
而不是Finite 1
有没有办法解决这些问题?上面的[Void]
、[()]
、X
和Y
的通用实例都已定义且正确吗?
{-# LANGUAGE DeriveGeneric, TypeFamilies, ScopedTypeVariables, UnicodeSyntax
, TypeApplications, AllowAmbiguousTypes
, DataKinds, PolyKinds, DefaultSignatures
, FlexibleInstances, DeriveAnyClass #-}
import GHC.Generics
import Numeric.Natural
import Data.Void
import Data.Proxy
import GHC.TypeLits
data Cardinality = Finite Natural | Infinite
deriving (Show)
instance Sized Void where cardinalityIC _ = Finite 0
instance Sized () where cardinalityIC _ = Finite 1
instance Sized Bool where cardinalityIC _ = Finite 2
instance Sized a => Sized [a] where
cardinalityIC rctxt = case cardinalityIC @a rctxt of
Finite 0 -> Finite 1
_ -> Infinite
data TypeIdentifier = TypeIdentifier
{ typeName, moduleName, packageName :: String }
deriving (Eq, Show)
class GSized f where gcardinalityIC :: [TypeIdentifier] -> Cardinality
class Sized a where
cardinalityIC :: [TypeIdentifier] -> Cardinality
default cardinalityIC :: (Generic a, GSized (Rep a))
=> [TypeIdentifier] -> Cardinality
cardinalityIC = gcardinalityIC @(Rep a)
cardinality :: ∀ a . Sized a => Cardinality
cardinality = cardinalityIC @a []
instance GSized V1 where gcardinalityIC _ = Finite 0
instance GSized U1 where gcardinalityIC _ = Finite 1
instance GSized f => GSized (M1 C c f) where gcardinalityIC = gcardinalityIC @f
instance GSized f => GSized (M1 S c f) where gcardinalityIC = gcardinalityIC @f
instance (GSized f, KnownSymbol tn, KnownSymbol mn, KnownSymbol pn)
=> GSized (D1 ('MetaData tn mn pn nt) f) where
gcardinalityIC rctxt
| thisType`elem`rctxt = Infinite
| otherwise = gcardinalityIC @f $ thisType : rctxt
where thisType = TypeIdentifier
(symbolVal $ Proxy @tn)
(symbolVal $ Proxy @mn)
(symbolVal $ Proxy @pn)
moduleName = symbolVal $ Proxy @tn
instance (GSized f, GSized g) => GSized (f :+: g) where
gcardinalityIC rctxt = case (gcardinalityIC @f rctxt, gcardinalityIC @g rctxt) of
(Finite n, Finite n') -> Finite (n+n')
_ -> Infinite
instance (GSized f, GSized g) => GSized (f :*: g) where
gcardinalityIC rctxt = case (gcardinalityIC @f rctxt, gcardinalityIC @g rctxt) of
(Finite 0, _) -> Finite 0
(_, Finite 0) -> Finite 0
(Finite n, Finite n') -> Finite (n*n')
_ -> Infinite
instance Sized c => GSized (K1 i c) where
gcardinalityIC = cardinalityIC @c
data Foo = F0 Bool | F1 Bool
deriving (Generic, Sized)
data Bar = B0 Bool | B1 Bar
deriving (Generic, Sized)
data Never = Never Never
deriving (Generic, Sized)
ghci> cardinality @Foo
Finite 4
ghci> cardinality @Bar
Infinite
ghci> cardinality @Never
Infinite
正如李耀霞所说,最后一个没有意义,因为nevernever
没有NF non-⊥ 价值观不确定是否有一个好的方法来考虑这一点。
问题内容: 是否可以在Java中以反射方式实例化泛型?使用此处描述的技术,由于类标记不能通用,我会遇到错误。请看下面的例子。我想实例化一些实现Creator的Creator子类。实际的类名作为命令行参数传递。这个想法是为了能够在运行时指定Creator的实现。还有另一种方法可以完成我在这里要做的事情吗? 编辑:我喜欢Marcus的方法,因为它是最简单,最实用的方法,不会绕开整个泛型的东西。我可以在
我想为我的Hazelcast集群计算一个最佳的分区数,但是,我找不到一个参数来作为计算的基础。271的默认分区可能足够,也可能不够,我不确定。 为了简单起见,如果我假设我的集群将有大约5000万个条目在50个节点上拆分,那么理想的分区数量是多少以及如何派生到这个数字? 谢谢你,迪利什
在这一点上,如果你有兴趣像MPL一样进行类型计算,你可能会想知道Hana如何帮助你。不用担心,Hana提供了一种通过将类型表示为值来执行具有大量表达性的类型计算的方法,就像我们将编译时数字表示为值一样。 这是一种全新的接触元编程的方法,如果你想熟练使用Hana,你应该尝试将你的旧MPL习惯放在一边。 但是,请注意,现代C++的功能,如自动推导返回类型,在许多情况下不需要类型计算。 因此,在考虑做一
那也许我可以 还是这是不可能的?也许只有在编译时了解了所有的信息,您才能做这种事情?
TypeScript在定义Type的时候,我们一般叫做类型,请问是否可以称为数据类型, 或者数据结构类型呢?
问题内容: 我可以在python中计算exp(1 + 2j)吗? 问题答案: 您需要此功能的复杂版本: 参见http://docs.python.org/library/cmath.html