2016-08-02 3 views
0

Есть ли способ иметь список пар без одинаковых типов в Haskell и выполнять функцию, пересекающую его. Например:Кортежи с различными типами

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

хотение применять функцию в зависимости от типа второго значения, что-то вроде функции, которая оценивает сочетание пары f :: [(Int, #)] -> [a].

+0

Я не думаю, что в настоящее время это возможно без расширения 'ImpredicativeTypes', которое в настоящее время [действительно не работает] (http://stackoverflow.com/q/33741334/465378). –

+5

@AlexisKing 'ImpredicativeTypes' вам не поможет. Импрессивность позволяет вам параметризовать типы с помощью 'forall'-quantified типов, например, для создания _homogeneous_ списка полиморфных функций. OP хочет построить _heterogeneous_ список мономорфных кортежей. –

+4

@jonaprieto Чего вы пытаетесь достичь? Самый простой способ - создать тип суммы и выполнить анализ событий во время выполнения: 'a :: [(Int, Either 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

Как утверждают другие, данная проблема не имеет решения. Но ваша реальная проблема заключается в том, что ваши данные не описываются списком кортежей. По определению список гомогенный (все элементы содержат один и тот же тип), в то время как ваши данные являются гетерогенными.

Если вы хотите написать функцию в зависимости от типа, вы должны как-то сохранить тип на уровне уровня.

Ваш пример данных фактически описывается типом Prod ((,) Integer) '[String, Bool, Integer], где Prod является следующий тип:

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

infixr 5 :> 

или в более общем Prod ((,) Integer) xs для некоторого списка типов xs.

Ваш пример значение затем

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, по крайней мере, TypeFamilies, GADTs, ConstraintKinds, DataKinds, PolyKinds.

Смежные вопросы