2016-08-02 51 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