[haskel] работа с existential типами
Насколько я понимаю, этого сделать нельзя. Квантифицированный типы нужны для чего-то типа инкапсуляции.
Вот например, если есть
То можно сделать
Но нельзя
Потому что по типу параметра (Stream a) нельзя определить тип выходного значения, он квантифицирован.
См. пункт 7.4.4.4 мануала GHC
Вот например, если есть
data Stream a = forall t. Stream t (t-> t) (t->a)
То можно сделать
get (Stream seed trans out) = out seed
next (Stream seed trans out) = Stream (trans seed) trans out
Но нельзя
state (Stream seed trans out) = seed
Потому что по типу параметра (Stream a) нельзя определить тип выходного значения, он квантифицирован.
См. пункт 7.4.4.4 мануала GHC
можешь писать функции с объявлением типов? А то я новичок в хаскеле и без них путаюсь.
Сейчас я расскажу, что я хотел сделать в упрощённом виде.
Мне нужно уметь сравнивать с произвольным типом (для фильтрации). Для этого я ввёл тип, который хранит
1) способ приведения к одному виду: (u->a)
2) коллекцию типа a для сравнения: DS.Set a
Потом я хотел бы записать список этих сравнения [u->aDS.Set a)] и последовательно foldl фильтровать коллекцию на основе этих данных.
Что у меня не вышло: вытащить данные из existential type.
Сейчас я расскажу, что я хотел сделать в упрощённом виде.
Мне нужно уметь сравнивать с произвольным типом (для фильтрации). Для этого я ввёл тип, который хранит
1) способ приведения к одному виду: (u->a)
2) коллекцию типа a для сравнения: DS.Set a
Потом я хотел бы записать список этих сравнения [u->aDS.Set a)] и последовательно foldl фильтровать коллекцию на основе этих данных.
Что у меня не вышло: вытащить данные из existential type.
можешь писать функции с объявлением типов? А то я новичок в хаскеле и без них путаюсь.
get :: Stream a -> a
next :: Stream a -> Stream a
А вот тип функции state не входит в систему типов Хаскеля. Тип
Stream a -> tозначает, что по любому представителю типа Stream a мы можем получить элемент любого типа t, что в этом случае нам не подходит.
Насчет задачи - если тебе в результате надо получать что-то содержащее в явном виде тип a, то его квантифицировать не надо.
Я бы написал что-нибудь такое:
{-# LANGUAGE MultiParamTypeClasses #-}
class Transform a b where
transform :: a -> b
filterLess :: (Ord u, Ord a, Transform u a) => u -> [a] -> [a]
filterLess e xs = filter (< transform e) xs
Но это если способ приведения одного типа к другому однозначен.
да нет. Приводить можно к разным типам. Объявлять столько классов, сколько бывает разных v в (u->v)?
да нет. Приводить можно к разным типам. Объявлять столько классов, сколько бывает разных v в (u->v)?не классов, а инстансов
Вот пример:
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, IncoherentInstances #-}
module Main where
class Transform a b where
transform :: a -> b
filterLess :: (Ord u, Ord a, Transform u a) => u -> [a] -> [a]
filterLess e xs = filter (< transform e) xs
instance Transform Bool Integer where
transform x = if x then 1 else 0
instance Transform Bool String where
transform x = if x then "z" else ""
instance (Integral a) => Transform Integer a where
transform = fromInteger
instance (Show a) => Transform a String where
transform = show
instance (Integral a) => Transform a [] where
transform 0 = []
transform (i+1) = :(transform i)
transform _ = error "Negative integer transformed to []"
main :: IO
main = do
print $ filterLess True ([-3..3]::[Integer])
print $ filterLess 3 ["00a", "123", "300", "456"]
print $ filterLess 3 [[], [], [], []]всё, я решил проблему - отдельные функции не понадобились, т.к. везде подставил паттерн матчинг
Оставить комментарий
yroslavasako
Обнаружил замечательное расширение ghc, но не вполне понял, как его нужно использовать.Есть объявление типа:
ghc жрёт это объявление типа нормально
пытаюсь написать функцию, которая возвращает первое значение в кортеже (u->a) - но никак не выходит, получаются одни ошибки. Подскажите, как это сделать правильно.