Haskell:按类型过滤异构列表

时间:2012-02-22 13:44:52

标签: haskell filter

我们可以使用对序列在Haskell中创建异构列表:

type a *: b = (a, b)
a *: b = (a, b)
infixr 5 *:

hlist :: Int *: String *: Maybe Float *: ()
hlist = 1 *: "hello" *: Just 3 *: () -- (1, ("hello", (Just 3, ())))

我们可以在这些列表上进行类型级别过滤吗?也就是说,定义一些多态函数hfilter,以便对于不同类型abc

hfilter :: a *: b *: c *: a *: b *: a *: () ->  a *: a *: a *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () ->  b *: b *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () ->  c *: ()
hfilter :: a *: b *: c *: a *: b *: a *: () ->  ()

2 个答案:

答案 0 :(得分:16)

可以使用一些类型扩展(另外,请在发布问题时检查您的示例代码是否已编译。我必须进行相当多的更正。)

{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE OverlappingInstances #-}

type a :* b = (a, b)
a *: b = (a, b)
infixr 5 *:
infixr 5 :*

hlist :: Int :* String :* Int :* Maybe Float :* ()
hlist = 1 *: "hello" *: 2 *: Just 3 *: ()


class TypeFilter lst t where
    hfilter :: lst -> [t]

instance TypeFilter () t where
    hfilter _ = []

instance TypeFilter rest t => TypeFilter (t :* rest) t where
    hfilter (a, rest) = a : hfilter rest

instance TypeFilter rest t => TypeFilter (a :* rest) t where
    hfilter (_, rest) = hfilter rest

现在我们可以通过明确定义所需列表的类型来按类型过滤项目。

*Main> hfilter hlist :: [Int]
[1,2]
*Main> hfilter hlist :: [String]
["hello"]
*Main> hfilter hlist :: [Maybe Float]
[Just 3.0]
*Main> hfilter hlist :: [Maybe Int]
[]

它的工作原理是定义一个多参数类型类TypeFilter,它采用异构列表的类型和我们想要过滤的类型。然后,我们为空列表/单元()和类型匹配的列表(TypeFilter (t :* rest) t)定义实例,最后为头部类型与我们要检索的类型不同的列表定义实例(TypeFilter (a :* rest) t)

请注意,在最后一个实例中,目前无法表示at必须是不同的类型,但是当它们相同时OverlappingInstances计算实例{{1}更具体,并在TypeFilter (t :* rest) t上选择它。

答案 1 :(得分:2)

虽然存在执行所要求的方法,但您很可能不会在这里玩Haskell。你能详细说明你的需求吗?通常,您可以枚举代数数据类型中需要的所有变体。您的列表将是同类的,允许您对元素进行模式匹配以对其进行操作。