- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个如下所示的 GADT
data MyTypes
= MyInt
| MyDouble
data Test (t :: MyTypes) where
A :: Int -> Test 'MyInt
B :: Double -> Test 'MyDouble
这使我能够在类型级别跟踪 Test
值中包含的值,以便我也可以执行类似的操作
data Test2 (t :: MyTypes) where
A2 :: Test 'MyInt -> Test2 'MyInt
B2 :: Test 'MyDouble -> Test2 'MyDouble
并传递信息。
但是,如果我想要具有不同 MyTypes
的 Test
值列表,例如
myData :: [Test (t :: MyTypes)]
myData =
[ A (3 :: Int)
, B (5.0 :: Double)
]
我得到了预期的‘t’是一个刚性类型变量绑定(bind)
错误消息。
我尝试使用存在类型来克服严格类型变量的问题,但随后我失去了传递有关 MyType
的类型级别信息的能力。
遇到这样的问题我该如何解决?
最佳答案
这里的解决方案是存在主义的:
data Test a where
A :: Int -> Test Int
B :: Double -> Test Double
data SomeTest where
SomeTest :: Test a -> SomeTest
myData :: [SomeTest]
myData =
[ SomeTest (A (3 :: Int))
, SomeTest (B (5.0 :: Double))
]
这只会改变您使用这种类型的方式。您可以通过模式匹配来恢复类型信息:
consume :: Test a -> Int
consume (A a) = a + 1
consume (B b) = truncate b
map (\ (SomeTest x) -> consume x) myData :: [Int]
使用 RankNType
,您可以使用恢复类型的延续来解开它:
test :: (forall a. Test a -> r) -> SomeTest -> r
test k (SomeTest x) = k x
test (\ x -> case x of
A a -> a + 1 {- ‘a’ is known to be ‘Int’ here -}
B b -> truncate b {- ‘b’ is known to be ‘Double’ here -})
:: SomeTest -> Int
当您使用它来将多个事物打包在某种“模块”中时,没有任何类型类约束的存在性非常有用,其中它们都必须就类型达成一致,但该类型是从外面看不透明。这限制了消费者可以执行的操作 - 例如,考虑一对请求和一个用于存储该请求结果的变量:
data SomeRequest where
SomeRequest :: IO a -> IORef a -> SomeRequest
fetchRequests :: [SomeRequest] -> IO ()
fetchRequests = traverse_ fetchRequest
where
-- ‘fetchRequest’ controls the fetching strategy (sync/async)
-- but can’t do anything with the fetched value
-- other than store it in the ‘IORef’.
fetchRequest :: SomeRequest -> IO ()
fetchRequest (SomeRequest request result) = do
value <- request
writeIORef result value
如果你有一个完全多态的类型,比如:
data Test a where
Test :: a -> Test a
然后您可以通过添加类型类约束来恢复有关类型的更多有趣信息。例如,如果您想要完整的动态信息,可以使用 Typeable
获取:
data SomeTest where
SomeTest :: Typeable a => Test a -> SomeTest
test :: (forall a. Typeable a => Test a -> r) -> SomeTest -> r
test k (SomeTest x) = k x
test (\ (Test a) -> case cast a of
Just a' -> (a' :: Int) + 1
Nothing -> case cast a of
Just a' -> length (a' :: String)
Nothing -> 0)
大多数时候,您可以使用比这更弱的类型类,具体取决于您实际需要的操作。
关于haskell - 异构 GADT 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49519247/
我有一个 NSTreeController (向 NSOutlineView 提供内容)。我希望顶级对象属于一个类,而所有其他对象(因此,任何级别的子对象)属于另一个类。解决这个问题的最佳方法是什么?
我有一个如下所示的 GADT data MyTypes = MyInt | MyDouble data Test (t :: MyTypes) where A :: Int -
我需要一个高效的异构数组,其中第一个元素是 int,其余是 float。然而,创建它之后,基本的数组操作就会呈爆炸式增长。 A = np.zeros(1, dtype='i4, f4, f4') B
我有一个 pandas DataFrame,其中包含需要拆分成平衡切片的字符串和浮点列,以便训练 sklearn 管道。 理想情况下,我会使用 StratifiedKFold在 DataFrame 上
是否有一种异构容器的形式,能够存储例如不同的基本类型(例如int、float、double)? 最终我希望能够在计算中使用元素而无需显式引用类型,例如 auto res = a + b,其中操作数 a
假设我有一个结构(或类),如下所示: struct _particle { std::vector vx , vy; std::vector id; std::vector rx, ry; }; ty
我在将具有 > 22 列的表专门映射到 case class 时遇到问题,假设您有以下代码 import slick.driver.PostgresDriver import scala.slick.
我是一名优秀的程序员,十分优秀!