2016-08-02 106 views
0

有没有在Haskell中具有相同类型的对列表的任何方法,并使函数遍历它。例如:不同类型的元组

a = [(1, "uno"), (2, True), (3, 5)] 

甲要应用根据第二值的类型,如,用于评估对f :: [(Int, #)] -> [a].

+0

如果没有'ImpredicativeTypes'扩展名,目前[并不真正工作](http://stackoverflow.com/q/33741334/465378),我不认为这是可能的。 –

+5

@AlexisKing'ImpredicativeTypes'不会帮你在这里。 Impredicativity允许你通过'forall'量化的类型来参数化类型,例如做一个多态函数的_homogeneous_列表。 OP想要构建一个单形元组的_heterogeneous_列表。 –

+4

@jonaprieto你想达到什么目的?最简单的方法是构建一个sum类型,并对这些值进行运行时实例分析:'a :: [(Int,Bool String)]' –

回答

4

只需将值包装在求和类型中。例如,

data StringOrBoolOrInt = 
    StringOrBoolOrInt_String String | 
    StringOrBoolOrInt_Bool Bool | 
    StringOrBoolOrInt_Int Int 

a :: [(Int, StringOrBoolOrInt)] 
a = 
    [ 
    (1, StringOrBoolOrInt_String "uno"), 
    (2, StringOrBoolOrInt_Bool True), 
    (3, StringOrBoolOrInt_Int 5) 
    ] 
6

To a first approximation的组合的功能的东西的函数,不,这是不可能的。首先对值进行标准化,例如通过在将每个第二个参数放到元组中之前对其应用一些类 - 多态函数。

1

正如其他人所说的那样,这个问题没有解决方案。但是你真正的问题是你的数据不是由元组列表描述的 - 根据定义,列表是同质的(所有元素都包含相同的类型),而你的数据是异构的。

如果要根据类型编写函数,必须以某种方式将类型存储在类型级别上。

data Prod f (xs :: [a]) where 
    P0 :: Prod f '[] 
    (:>) :: f x -> Prod f xs -> Prod f (x ': xs) 

infixr 5 :> 

或更一般地为Prod ((,) Integer) xs类型xs一些列表:

你的示例数据实际上是由类型Prod ((,) Integer) '[String, Bool, Integer],其中Prod是以下类型描述。

你的榜样值此时

a = (1, "uno") :> (2, True) :> (3, 5) :> P0 

您可以对这些类型使用普通方法分支 - 即一个类型的类。假设一个有这样一类:

class HasFoo x where 
    foo :: x -> Integer 

instance HasFoo String where foo = fromIntegral . length 
instance HasFoo Bool where foo = fromIntegral . fromEnum 
instance HasFoo Integer where foo = id 

可以应用这样的foo功能,为您的产品

type family All (c :: k -> Constraint) (xs :: [k]) :: Constraint where 
    All c '[] =() 
    All c (x ': xs) = (c x, All c xs) 

-- example operation: add everything 
fooProd :: All HasFoo xs 
     => Prod ((,) Integer) xs 
     -> Integer 
fooProd P0 = 0 
fooProd ((i, x) :> ps) = i + foo x + fooProd ps 

的每一个元素这需要一些GHC扩展,至少TypeFamiliesGADTsConstraintKindsDataKindsPolyKinds