如何声明多态集合类型的标记联合
How declare tagged union of polymorphic collection types
我是 Purescript 的新手。我目前的学习练习是创建多态数组和列表的标记联合。我将在查找任何数组或列表长度的函数中使用它。这是我的尝试:
import Data.List as L
import Data.Array as A
data Collection = CollectionList (forall a. L.List a)
| CollectionArray (forall b. Array b)
colLength :: Collection -> Int
colLength (CollectionList list) = L.length list
colLength (CollectionArray arr) = A.length arr
main :: Effect Unit
main = do
logShow (colLength (CollectionArray [3,5]))
编译器不喜欢:
Could not match type Int with type b0
while checking that type Int is at least as general as type b0
while checking that expression 3 has type b0
in value declaration main
where b0 is a rigid type variable
我对 checking that type Int is at least as general as type b0
和 b0 is a rigid type variable
这两个部分感到困惑。我的意图是让 b
成为任何东西。不确定我做了什么让编译器为 b
设置条件。
如果您知道如何操作,请展示定义将在我的 colLength
函数中工作的标记的多态类型并集的正确方法。
forall a
并不意味着“任何类型都在这里”
这意味着谁访问这个值,谁就可以选择a
是什么,谁提供这个值就拥有以确保该值属于该类型。这是提供者和消费者之间的合同。
因此,当您提供值 CollectionArray [3,5]
时,您必须使其能够 对所有 可能 a
以后访问该值的人有效可能会选择。
显然,只有一种方法可以构建这样的值:
CollectionArray []
您可能 实际上 打算做的(我在这里猜测)是使您的集合多态化,因为它可以包含任何类型的值,但是类型由 创建 集合的人选择,然后访问它的人必须处理该特定类型。
为此,您必须将类型变量放在外面:
data Collection a = CollectionList (L.List a)
| CollectionArray (Array a)
这样,当你创建一个集合 CollectionArray [3,5]
时,它变成了 Collection Int
类型,现在你传递它的任何地方,比如 colLength
,都必须处理那个Int
反过来,这可以通过使 colLength
本身通用来实现:
colLength :: forall a. Collection a -> Int
colLength (CollectionList list) = L.length list
colLength (CollectionArray arr) = A.length arr
现在无论谁访问(即调用)colLength
本身都可以选择 a
是什么,这很好用,因为它是最初创建 Connection Int
的同一个地方.
我是 Purescript 的新手。我目前的学习练习是创建多态数组和列表的标记联合。我将在查找任何数组或列表长度的函数中使用它。这是我的尝试:
import Data.List as L
import Data.Array as A
data Collection = CollectionList (forall a. L.List a)
| CollectionArray (forall b. Array b)
colLength :: Collection -> Int
colLength (CollectionList list) = L.length list
colLength (CollectionArray arr) = A.length arr
main :: Effect Unit
main = do
logShow (colLength (CollectionArray [3,5]))
编译器不喜欢:
Could not match type Int with type b0
while checking that type Int is at least as general as type b0
while checking that expression 3 has type b0
in value declaration main
where b0 is a rigid type variable
我对 checking that type Int is at least as general as type b0
和 b0 is a rigid type variable
这两个部分感到困惑。我的意图是让 b
成为任何东西。不确定我做了什么让编译器为 b
设置条件。
如果您知道如何操作,请展示定义将在我的 colLength
函数中工作的标记的多态类型并集的正确方法。
forall a
并不意味着“任何类型都在这里”
这意味着谁访问这个值,谁就可以选择a
是什么,谁提供这个值就拥有以确保该值属于该类型。这是提供者和消费者之间的合同。
因此,当您提供值 CollectionArray [3,5]
时,您必须使其能够 对所有 可能 a
以后访问该值的人有效可能会选择。
显然,只有一种方法可以构建这样的值:
CollectionArray []
您可能 实际上 打算做的(我在这里猜测)是使您的集合多态化,因为它可以包含任何类型的值,但是类型由 创建 集合的人选择,然后访问它的人必须处理该特定类型。
为此,您必须将类型变量放在外面:
data Collection a = CollectionList (L.List a)
| CollectionArray (Array a)
这样,当你创建一个集合 CollectionArray [3,5]
时,它变成了 Collection Int
类型,现在你传递它的任何地方,比如 colLength
,都必须处理那个Int
反过来,这可以通过使 colLength
本身通用来实现:
colLength :: forall a. Collection a -> Int
colLength (CollectionList list) = L.length list
colLength (CollectionArray arr) = A.length arr
现在无论谁访问(即调用)colLength
本身都可以选择 a
是什么,这很好用,因为它是最初创建 Connection Int
的同一个地方.