含有 GADT 的载体
Vector containing GADT
我正在尽我所能学习有关 ExistentialQuantification、GADT 和 KindSignatures 等的所有知识。为此,我尝试编写一些小程序来帮助我更好地理解所有内容。
现在我有了这个小片段(它实际上可以编译,所以你可以自己尝试,需要 vector 和 mtl 包) 并想知道是否有可能完成我想要完成的事情或指导我如何让它发挥作用
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
import Control.Monad.State.Lazy
import qualified Data.Vector as V
data MenuItem = ListS | ActionS | SliderS
data MenuItemReference (a :: MenuItem) (n :: *) where
MenuListSReference :: Int -> MenuItemReference ListS Int
MenuActionSReference :: Int -> MenuItemReference ActionS Int
MenuSliderSReference :: Int -> MenuItemReference SliderS Int
data MyState = MyState { vec :: forall a. V.Vector (MenuItemReference a Int) }
newMyState :: MyState
newMyState = MyState { vec = V.empty }
listRef :: MenuItemReference ListS Int
listRef = MenuListSReference 5
actionRef :: MenuItemReference ActionS Int
actionRef = MenuActionSReference 3
myComputation :: State MyState ()
myComputation = do
addItem listRef
addItem actionRef
return ()
addItem :: forall a. MenuItemReference a Int -> State MyState ()
addItem menuItemRef = do
s <- get
put (s { vec = (vec s) `V.snoc` menuItemRef })
main :: IO ()
main = do
print $ evalState myComputation newMyState
如您所见,我正在尝试在其中获取 MenuItemReferences 的 Vector...我做错了什么,因为我现在所拥有的错误:
Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for
addItem :: MenuItemReference a Int -> State MyState ()
at Main.hs:34:19
‘a1’ is a rigid type variable bound by
a type expected by the context: V.Vector (MenuItemReference a1 Int)
at Main.hs:37:10
Expected type: MenuItemReference a1 Int
Actual type: MenuItemReference a Int
Relevant bindings include
menuItemRef :: MenuItemReference a Int (bound at Main.hs:35:9)
addItem :: MenuItemReference a Int -> State MyState ()
(bound at Main.hs:35:1)
In the second argument of ‘V.snoc’, namely ‘menuItemRef’
In the ‘vec’ field of a record
有人可以解释错误背后的原因是什么以及我如何处理(如果可能的话)我正在努力完成的事情。
为什么不只是
data MenuItemReference =
MenuListSReference Int |
MenuActionSReference Int |
MenuSliderSReference Int
然后呢?
使用的构造函数已经注释了该值。你不需要注入幻像类型,因为信息已经存在。
此外,这样做需要启用 GHC({-# LANGUAGE ImpredicativeTypes #-}
) to actually support impredicative polymorphism 来构建 Vector [forall a. MenuItemReference a Int]
并以多态方式使用它。虽然它支持这一点,但该支持被描述为 "fragile at best and broken at worst"。
作为旁注,this nice blog post 解释了我们如何使用 newtype
s 和 RankNTypes
来摆脱非谓语类型。但是,这确实需要您引入一层 newtype
。
我正在尽我所能学习有关 ExistentialQuantification、GADT 和 KindSignatures 等的所有知识。为此,我尝试编写一些小程序来帮助我更好地理解所有内容。
现在我有了这个小片段(它实际上可以编译,所以你可以自己尝试,需要 vector 和 mtl 包) 并想知道是否有可能完成我想要完成的事情或指导我如何让它发挥作用
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
import Control.Monad.State.Lazy
import qualified Data.Vector as V
data MenuItem = ListS | ActionS | SliderS
data MenuItemReference (a :: MenuItem) (n :: *) where
MenuListSReference :: Int -> MenuItemReference ListS Int
MenuActionSReference :: Int -> MenuItemReference ActionS Int
MenuSliderSReference :: Int -> MenuItemReference SliderS Int
data MyState = MyState { vec :: forall a. V.Vector (MenuItemReference a Int) }
newMyState :: MyState
newMyState = MyState { vec = V.empty }
listRef :: MenuItemReference ListS Int
listRef = MenuListSReference 5
actionRef :: MenuItemReference ActionS Int
actionRef = MenuActionSReference 3
myComputation :: State MyState ()
myComputation = do
addItem listRef
addItem actionRef
return ()
addItem :: forall a. MenuItemReference a Int -> State MyState ()
addItem menuItemRef = do
s <- get
put (s { vec = (vec s) `V.snoc` menuItemRef })
main :: IO ()
main = do
print $ evalState myComputation newMyState
如您所见,我正在尝试在其中获取 MenuItemReferences 的 Vector...我做错了什么,因为我现在所拥有的错误:
Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for
addItem :: MenuItemReference a Int -> State MyState ()
at Main.hs:34:19
‘a1’ is a rigid type variable bound by
a type expected by the context: V.Vector (MenuItemReference a1 Int)
at Main.hs:37:10
Expected type: MenuItemReference a1 Int
Actual type: MenuItemReference a Int
Relevant bindings include
menuItemRef :: MenuItemReference a Int (bound at Main.hs:35:9)
addItem :: MenuItemReference a Int -> State MyState ()
(bound at Main.hs:35:1)
In the second argument of ‘V.snoc’, namely ‘menuItemRef’
In the ‘vec’ field of a record
有人可以解释错误背后的原因是什么以及我如何处理(如果可能的话)我正在努力完成的事情。
为什么不只是
data MenuItemReference =
MenuListSReference Int |
MenuActionSReference Int |
MenuSliderSReference Int
然后呢?
使用的构造函数已经注释了该值。你不需要注入幻像类型,因为信息已经存在。
此外,这样做需要启用 GHC({-# LANGUAGE ImpredicativeTypes #-}
) to actually support impredicative polymorphism 来构建 Vector [forall a. MenuItemReference a Int]
并以多态方式使用它。虽然它支持这一点,但该支持被描述为 "fragile at best and broken at worst"。
作为旁注,this nice blog post 解释了我们如何使用 newtype
s 和 RankNTypes
来摆脱非谓语类型。但是,这确实需要您引入一层 newtype
。