Aleksei (astynax)
zipWith' f xs ys = takeWhile isJust $ zipWith (liftA2 f) (wrap xs) (wrap ys) where wrap zs = Just <$> zs ++ repeat Nothing
Aleksei (astynax)
Так. Походу у меня обычный zipWith получился :)
Aleksei (astynax)
Кароч, нужно просто зипать через Maybe a -> Maybe b -> Maybe c и будет нормально - контроль над остановом, вот это всё: zipWith' f xs ys = takeWhile isJust $ zipWith f (wrap xs) (wrap ys) where wrap zs = Just <$> zs ++ repeat Nothing
Алексей ayaye :)
A64m
инстанс Alternative для ZipList появился. раньше такого не было
Ilya
и как это поможет?
ну я выше же привёл код
A64m
да, комбинаторный парсер (инстансы апликатив и альтернатив) как обычно не победить
кана
когда только знакомился с хаскелем, долго мучала идея, как сделать псевдогетерогенный список, где элементы чередуются единственная идея, которая тогда пришла - делать специальные отдельные списки, где не 2 конструктора, а типа: data IntAndStringList = Nil | PartCons Int | Cons Int String IntAndStringList
кана
сейчас вспомнил о задаче (из-за другой книги, где рассказывается про индукцию как рекурсию, параметризованую значениями элементов, зависимую то есть) и пришла идея просто параметризовать тип каждого элемента индексом (от 0, если от 1, то Cons :: a (Succ n) ->)
кана
Ilya
а какая задача? сделать типа список, где могут лежать элементы двух разных типов, причём строго по очереди?
кана
"сделать псевдогетерогенный список, где элементы чередуются"
кана
да
Ilya
интересно
eahqzsr
А доставать как?
Timofey
А чем проще всего собрать лог работы приложения и выгрузить в конце в файлик?
кана
ща попробую написать индуктивный элиминатор
Ilya
@kana_sama a у тебя список может начинаться с любого из типов?
Ilya
или только с одного из двух
кана
@kana_sama a у тебя список может начинаться с любого из типов?
тип элемента задается семейством, в данном случае в семействе задали, что IntString 0 = Int
Ilya
нет, я про исходную задачу
Ilya
решение с семействами не смотрел, хочу что-нибудь своё пока придумать:)
кана
в исходной задаче не было конкретной формулировки, она спонтанно родилась и забылась будем считать, что первый элемент статичен
Ilya
просто вот здесь как будто в конце обязательно должен быть Int, а строка быть не может
в твоей первой реализации, "когда ты только начинал знакомиться"
кана
Cons 1 "2" Nil
Ilya
а, ок
Ilya
просто тип выглядел несимметричным
кана
А доставать как?
похоже с семейством никак, нужно использовать gadt-ы
кана
потому что я не могу сматчить IntegerString n
кана
Ilya
тип example обязательно вручную писать?
кана
нет, выведется
Ilya
отлично тогда
Ilya
то есть ради чего усложняем?
кана
необобщенность
кана
можно обобщить по двум типам, но если мы захотим чередование по 3?
кана
а потом по 4
кана
в новом решении есть общий DVector, а сколько и как (там может быть и не чередование, а другая комплексная логика, например вектор из векторов такой же длины, чтобы такой треугольник получился) - решает клиент
Ilya
Ох уж эти клиенты:))
Cheese
@kana_sama data Rope a b = Nil | a :. Rope b a
кана
@kana_sama data Rope a b = Nil | a :. Rope b a
тут чередование только двух элементов
кана
для трех придется писать новый тип
кана
наверное можно через семейство по тайплевел спискам обобщить до N типов
кана
но выглядит красиво конечно, намного лучше того моего
кана
собственно вот
кана
обобщить бы как-нибудь до List, чтобы Rope '[] стало Void
кана
без проблем data Rope (ts :: [Type]) where Nil :: Rope ts (:~) :: Head ts -> Rope (Shift ts) -> Rope ts работать с таким типом еще сложнее, чем с "зависимым вектором выше"
Alexander
а зачем так?
Alexander
у шифта можно '[] не делать
кана
без проблем data Rope (ts :: [Type]) where Nil :: Rope ts (:~) :: Head ts -> Rope (Shift ts) -> Rope ts работать с таким типом еще сложнее, чем с "зависимым вектором выше"
чтобы его элиминировать, нужно делать какую-то n+1 арную функцию, где n - длина списка, на тайпклассах
Alexander
тогда Rope '[] только Nil, хотя оно и так
Alexander
там unary tuple вроде подвезут
Alexander
так меня можно игнорировать
кана
у шифта можно '[] не делать
да, в принципе и у head [] можно не делать, что позволит обобщить head до k
кана
я так понимаю, неопределенный кейс семейства - то же самое, что и void
кана
раньше я думал, что не скомпилируется
кана
type family Head (as :: [k]) :: k where Head (a : as) = a y :: Head '[] y = undefined
Alexander
интересно а. можно ли обощить, б. можно ли без GADT
Alexander
обощить наверное можно щас попробую
Cheese
type family Head (as :: [k]) :: k where Head (a : as) = a y :: Head '[] y = undefined
чтобы этого избегать, придумали TypeError
Alexander
почему я всегда забываю хак с частичным примерением TF
кана
превосходно
Alexander
обощил
Alexander
https://gist.github.com/qnikst/785feaecb43b032ef21415576d85209d
Alexander
через nested types без гадтов наверное не получится
Alexander
правда elim там уже фиг напишешь так просто (скорее всего)
Vladislav
Я сделал штуковину https://hackage.haskell.org/package/unwrapped-functors-0.1.0.0/docs/Data-Functor-Unwrapped.html
Vladislav
Она достаточно тупая, но если взять Rec из vinyl и переписать там тип элементов с f r на Unwrapped f r, то получаются даже сносные гетерогенные списки
Vladislav
Ну то есть могут они строго меньше, но простые юз-кейсы становятся намного приятнее, например не нужно в Identity всё заворачивать
Vladislav
или в Const
Vladislav
я вот применил Product (Const x) Identity и получил для каждого элемента a тьюпл (x, a)
Vladislav
в более интересных новостях, добавил поддержку опциональных параметров в https://hackage.haskell.org/package/named-0.2.0.0/docs/Named.html
кана
https://gist.github.com/qnikst/785feaecb43b032ef21415576d85209d
классы тут по идее не нужны, хватит и просто инстансов семейств
кана
без проблем data Rope (ts :: [Type]) where Nil :: Rope ts (:~) :: Head ts -> Rope (Shift ts) -> Rope ts работать с таким типом еще сложнее, чем с "зависимым вектором выше"
в принципе получается это, только вместо конкретных Head/Shift получается семейство разных Head/Shift, параметризованное фантомом, которое находится в типе rope