我正在尝试编写两个函数来从 HList
中提取值,但我似乎无法让 GHC 满意。
第一个函数将具有签名 extract::HList a -> [b]
,它从列表中提取 b
类型的所有元素。我只是通过要求 a
中的类型具有 Typeable
实例才成功编写它。
class OfType a b where
oftype :: a -> [Maybe b]
instance OfType (HList '[]) b where
oftype = const []
instance (Typeable t, Typeable b, OfType (HList ts) b) => OfType (HList (t ': ts)) b where
oftype (x :- xs) = (cast x :: Maybe b) : oftype xs
extract :: OfType a b => a -> [b]
extract = catMaybes . oftype
这是次优的,因为实际上并不需要 Typeable
约束来编写任何 extract 实例。
我尝试在约束中使用类型相等和不等式,但这只会给我重叠的实例。
我尝试编写的第二个函数将具有签名 extract'::Contains h n => HList h -> n
,它提取 n
类型的第一个元素在列表中,并且上下文表明该列表实际上包含该类型的一个元素。
是否可以在没有 Typeable
约束的情况下编写extract
?
是否可以在没有 Typeable
约束的情况下编写 extract'
?
如何写Contains
?
最佳答案
由于您想在编译时检查类型相等性,因此我相信重叠实例是不可避免的(而且我不喜欢这些......)。
此外,我不能 100% 确定我的重叠编译指示正确无误。
{-# LANGUAGE DataKinds, TypeOperators, ScopedTypeVariables,
MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
{-# OPTIONS -Wall #-}
module HListFilter where
import Data.HList.HList
class OfType a b where
oftype :: a -> [b]
instance OfType (HList '[]) b where
oftype = const []
instance {-# OVERLAPS #-} (OfType (HList ts) t) => OfType (HList (t ': ts)) t where
oftype (HCons x xs) = x : oftype xs
instance {-# OVERLAPPABLE #-} (OfType (HList ts) b) => OfType (HList (t ': ts)) b where
oftype (HCons _ xs) = oftype xs
test :: HList '[Int, Char, [Char], Char, Bool]
test = HCons (1::Int) (HCons 'a' (HCons "foo" (HCons 'b' (HCons True HNil))))
test_result :: [Char]
test_result = oftype test -- "ab"
关于haskell - 在 HList 中查找元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35252562/