如何在Haskell中迭代异构递归值
我看到了HList的软件包,但我认为这对于我所需要的东西来说太过分了 我有这个:如何在Haskell中迭代异构递归值,haskell,Haskell,我看到了HList的软件包,但我认为这对于我所需要的东西来说太过分了 我有这个: data a :*: b = a :*: b deriving (Show, Eq) 我可以通过以下方法成功地完成这项工作: prepend :: a -> b -> a :*: b prepend a b = a :*: b 但是我希望能够以某种方式遍历“列表”并使用元素进行操作,但不确定如何操作。这里的以及可能有用的 基本迭代相对简单(前提是您能够轻松地思考本质上的Prolog),按元素类型(或
data a :*: b = a :*: b deriving (Show, Eq)
我可以通过以下方法成功地完成这项工作:
prepend :: a -> b -> a :*: b
prepend a b = a :*: b
但是我希望能够以某种方式遍历“列表”并使用元素进行操作,但不确定如何操作。这里的以及可能有用的
基本迭代相对简单(前提是您能够轻松地思考本质上的Prolog),按元素类型(或标签)匹配记录会让事情变得棘手:根据类型相等性做一些事情目前需要重叠实例,您将无法决定是否相等(大多数?全部?)多态类型
类型匹配很可能是“对元素做点什么”所需要的,这取决于什么是元素;删除很容易,应用一个函数(其参数必须与元素类型匹配)不是一件小事,但如果您可以给出元素的数字索引,则应该可以不使用编译器扩展
(编辑:这假设您希望对列表应用第一类函数。Rampion的回答显示了如何使用普通类型类轻松匹配类型,但类型类不能作为值传递。)
因此,最终可能会发现HList或葡萄柚记录并没有过度使用。请注意,您已经可以通过两种方式迭代列表:
ghci> let hetlist = (1 :: Int) :*: ("two" :: String) :*: (3.0 :: Double) :*: ()
ghci> hetlist
((1 :*: "two") :*: 3.0) :*: ()
ghci> hetlist == hetlist
True
您可以使用自己的TypeClass来模拟这一点:
class DoStuff a where
dostuff :: a -> a
instance DoStuff Int where dostuff i = 2*i
instance DoStuff String where dostuff s = s ++ s
instance DoStuff Double where dostuff d = d / 2
instance DoStuff () where dostuff () = ()
instance (DoStuff a, DoStuff b) => DoStuff (a :*: b) where
dostuff (a :*: b) = dostuff a :*: dostuff b
然后对集合进行迭代是自动的
ghci> dostuff hetlist
((2 :*: "twotwo") :*: 1.5) :*: ()
或者,您也可以使用和包装器类型执行同样的操作,
这样就不必定义自己的列表类型
data DoStuffWrapper = forall a. (DoStuff a) => DoStuffWrapper a
homlist = [ DoStuffWrapper (1 :: Int)
, DoStuffWrapper ("two" :: String)
, DoStuffWrapper (3.0 :: Double)
]
homlist' = map (\(DoStuffWrapper a) -> DoStuffWrapper (dostuff a)) homlist
附议@barsoap的建议。如果您确实需要可扩展性,那么可能很难比HList更简单。HList文件(当然是草稿)评论说,在类型级别列表中使用Nil比省略Nil更容易。问题中:*:的定义是pair,因此没有Nil..oO(Haskell的类型系统非常先进,可以使函数不是第一类;)是一个表达式问题!小心,:*:
现在是GHC.Generics中的(非)标准类型