Haskell - 构造一个使用存在量化的类型
Haskell - constructing a type that uses existential quantification
在下面的代码中,我使用存在量化定义了一个数据类型 F。我希望 F 类型的值包含接受单个参数并产生例如 Int 作为结果的函数。该参数需要实现一个类型 class ,我称之为 C,但现在留空。
这是我第一次尝试存在类型。我显然做错了什么,因为我似乎无法创建 F 类型的值。
{-# LANGUAGE ExistentialQuantification #-}
class C a where
data F = forall a. C a => F (a->Int)
makeF :: F
makeF = F $ const 1
如何修复这个编译错误?
No instance for (C a0) arising from a use of `F'
In the expression: F
In the expression: F $ const 1
In an equation for `makeF': makeF = F $ const 1
如果您重写您的 F
定义,它将起作用:
{-# LANGUAGE RankNTypes #-}
class C a where
data F = F (forall a. C a => a -> Int)
makeF :: F
makeF = F $ const 1
我自己也在努力理解为什么:
您的原始类型显示 "there exists a
which is instance of C
, and we have function a -> Int
"。
因此,要构造存在类型,我们必须说明我们有哪些 a
:
{-# LANGUAGE ExistentialQuantification #-}
class C a where
data F = forall a. C a => F (a -> Int)
-- Implement class for Unit
instance C () where
makeF :: F
makeF = F $ (const 1 :: () -> Int)
这些定义并不完全相同:
data G = forall a . C a => G {
value :: a -- is a value! could be e.g. `1` or `()`
toInt :: a -> Int, -- Might be `id`
}
data G' = G' {
value' :: C a => a -- will be something for every type of instance `C`
toInt' :: C a => a -> Int, -- again, by parametericity uses only `C` stuff
}
问题是 const 1
的类型是 forall a . C a => a -> Int
。当您将其传递给 F
时,我们失去了再次讨论类型 a
的机会,除了它是类型 C
.
的元素
遗憾的是,我们从未确定 a
必须是什么!
特别是,GHC 通过传入类型类 C 的 字典 来处理这样的存在性,该类型类 C 对应于存在性中实际结束的任何类型。由于我们从未向 GHC 提供足够的信息来查找该字典,因此它给了我们一个类型错误。
所以要解决这个问题,我们必须在某处实例化C
instance C Int
然后传递一个函数,该函数确定被遗忘的类型 a
实际上是 C
的一个实例
let x = F (const 1 :: Int -> Int)
在下面的代码中,我使用存在量化定义了一个数据类型 F。我希望 F 类型的值包含接受单个参数并产生例如 Int 作为结果的函数。该参数需要实现一个类型 class ,我称之为 C,但现在留空。
这是我第一次尝试存在类型。我显然做错了什么,因为我似乎无法创建 F 类型的值。
{-# LANGUAGE ExistentialQuantification #-}
class C a where
data F = forall a. C a => F (a->Int)
makeF :: F
makeF = F $ const 1
如何修复这个编译错误?
No instance for (C a0) arising from a use of `F'
In the expression: F
In the expression: F $ const 1
In an equation for `makeF': makeF = F $ const 1
如果您重写您的 F
定义,它将起作用:
{-# LANGUAGE RankNTypes #-}
class C a where
data F = F (forall a. C a => a -> Int)
makeF :: F
makeF = F $ const 1
我自己也在努力理解为什么:
您的原始类型显示 "there exists a
which is instance of C
, and we have function a -> Int
"。
因此,要构造存在类型,我们必须说明我们有哪些 a
:
{-# LANGUAGE ExistentialQuantification #-}
class C a where
data F = forall a. C a => F (a -> Int)
-- Implement class for Unit
instance C () where
makeF :: F
makeF = F $ (const 1 :: () -> Int)
这些定义并不完全相同:
data G = forall a . C a => G {
value :: a -- is a value! could be e.g. `1` or `()`
toInt :: a -> Int, -- Might be `id`
}
data G' = G' {
value' :: C a => a -- will be something for every type of instance `C`
toInt' :: C a => a -> Int, -- again, by parametericity uses only `C` stuff
}
问题是 const 1
的类型是 forall a . C a => a -> Int
。当您将其传递给 F
时,我们失去了再次讨论类型 a
的机会,除了它是类型 C
.
遗憾的是,我们从未确定 a
必须是什么!
特别是,GHC 通过传入类型类 C 的 字典 来处理这样的存在性,该类型类 C 对应于存在性中实际结束的任何类型。由于我们从未向 GHC 提供足够的信息来查找该字典,因此它给了我们一个类型错误。
所以要解决这个问题,我们必须在某处实例化C
instance C Int
然后传递一个函数,该函数确定被遗忘的类型 a
实际上是 C
let x = F (const 1 :: Int -> Int)