我们可以使用对序列在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
,以便对于不同类型a
,b
和c
:
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 *: () -> ()
答案 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)
。
请注意,在最后一个实例中,目前无法表示a
和t
必须是不同的类型,但是当它们相同时OverlappingInstances
计算实例{{1}更具体,并在TypeFilter (t :* rest) t
上选择它。
答案 1 :(得分:2)
虽然存在执行所要求的方法,但您很可能不会在这里玩Haskell。你能详细说明你的需求吗?通常,您可以枚举代数数据类型中需要的所有变体。您的列表将是同类的,允许您对元素进行模式匹配以对其进行操作。