Aleksei (astynax)
И нельзя писать f :: Num a
Aleksei (astynax)
Но можно f :: Num a => a
Aleksei (astynax)
Классы, это как-бы свойства типа. И мы пишем не
f :: Зелёноё, а
f :: что-то (но что-то зелёное) :)
Человек то умный, он может из первого вывести второе. А компилятор пока не готов к такому - ему нужно, чтобы был объект, пусть даже и со свойствами :)
Aleksei (astynax)
(ща набегут - как проснутся - и напишут, что я в корне неправ)
Нурлан
доня.
@newrlan на счёт ньютайпов, чтобы было немного понятнее, вот такой отвлечённый пример
есть класс моноид
и допустим те же целые числа являются одновременно моноидом и по сложению (с нейтральным нулём), и по умножению (с нейтральной единицей)
но два инстанса Monoid для одного типа Int мы конечно сделать не можем
но мы можем завести две обёртки:
newtype IntAddMonoid = IntAddMonoid Int
newtype IntMulMonoid = IntMulMonoid Int
и написать разные реализации тайпкласса Monoid для них, и таким образом избежать того что инстансы будут пересекаться
при этом так как это newtype а не data, никакого оверхеда в виде боксинга-анбоксинга в рантайме не будет (то есть в рантайме это будет просто Int, без всяких обёрток) + емнип там автодерайвятся всякие Coercible чтобы удобно было туда-сюда преобразовывать Int в IntAddMonoid/IntMulMonoid и обратно
Aleksei (astynax)
Да
Нурлан
Нурлан
Aleksei (astynax)
👍
Нурлан
Нурлан
теперь
Aleksei (astynax)
Да
Нурлан
и это не потребует затрат на лишнюю память?
Aleksei (astynax)
Нет :)
Нурлан
как на новую структуру данных?
Aleksei (astynax)
При компиляции newtype выкидывается. Т.е. никакого заворачивания/разворачивания не будет
Нурлан
Это круто!
Aleksei (astynax)
Нам тоже нравится :)
Нурлан
А можно еще один вопрос?
Aleksei (astynax)
Можно :)
Нурлан
я вот определил Num на Zpable, но я стремлюсь определить Fractional на Zpable
Нурлан
придется и на Num и на Fractional прописывать инстанс
Нурлан
или можно как-то это все в одну кучу собрать?
Alexander
нужно прописать инстансы для всех классов, может помочь расширение GeneralizedNewtypeDeriving
Alexander
GND работает так: разворачивает newtype, применяет инстанс базового типа и заворачивается обратно
Aleksei (astynax)
Num нельзя дерайвить, т.к. поведение зависит от инстанса Zp. Остальное можно, думается
Нурлан
вот теперь я хочу объявить тип пусть называется Zp61 как мне сказать что этот тип Zpable ?
Нурлан
я хочу прописать instance Zp Zp61 where
Нурлан
но я так понимаю, что мне нужно что бы Zp61 был типом Zpable (вот тут я уже поплыл)
Aleksei (astynax)
Не, Zpable нужет только для оборачивания существующих типов - Integer, Float, и т.п.
Aleksei (astynax)
Если есть кастомный тип, то для него инстансы можно писать, не оборачивая предварительно в Zpable
Нурлан
а как тогда написать instance Zp a => Num a ибо компилятор ругается
Aleksei (astynax)
А зачем такой инстанс писать то?
Aleksei (astynax)
Для Zp61 инстанс будет instance Num Zp61 where
Нурлан
ну у меня условно 100500 костомных типов, самое главное все они Zp
Нурлан
Нурлан
поэтому ввел Zp
Aleksei (astynax)
Тогда много конкретных инстансов
instance Zp (Zpable Zp61)
плюс один обобщённый
instance Zp (Zpable a) => Num (Zpable a)
Aleksei (astynax)
И все значения заворачивать в Zpable (или использовать численные литералы)
Alexander
Нурлан
Alexander
можно сделать newtype Zp (n::Nat) = Zp Int
Alexander
если 61 это модуль или что там из групп
Alexander
тогда написать инстанс для всего в соответствии с этим n
Alexander
и потом делать 1 :: Zp 35
Нурлан
Alexander
в n ?
Нурлан
да
Alexander
Nat ~ Integer но только положительные
Нурлан
Нурлан
я думал нельзя константы совать в объявления типов
Alexander
для отрицательных наверное надо будет Bool добавить чтобы вся машинерия работала
Alexander
в GHC.TypeLits есть кусок докумертации
Alexander
вообще это DataKinds + доп машинерия в ghc для того чтобы литералы можно было поднимать
Alexander
последнее для строк и натов есть
Alexander
но они не индуктивные будут
Alexander
для задачи наверное это и не нужно
Alexander
ghc пока ещё не идеально со всей этой машинерией работает, но если не нужно будет много вычислений на n то прокатит
Нурлан
Alexander
я к сожалению до ноутбука только к вечеру доберусь, так что полностью готовый пример со ссылками на релевантные статьи только вечером смогу сделать
Alexander
ну если на *тайплевел* термах будут всякие вычисления то там нужно очень следить за структурой чтобы доказать верность
Alexander
использование самих Zp не ограничивается
Alexander
просто если будет foo :: Zp n -> Zp m -> Zp (сложная формула от n m)
Alexander
то тайпчеккеру может плохо стать
Alexander
особенно если рядом будет другая сложная формула, которая сводится к тому же результату
Alexander
например доказать что Min n m = Min m n будет нетривиально
Alexander
есть пакет от кметта с аксиомами и плагин, но я схожу не помню
Alexander
в любом случае задачу это покрывать хорошо должно
Alexander
в модуле GHC.TypeLits есть всё для прыжков между type и value level
Cheese
есть какой-нибудь готовый тайпкласс или математический термин, обозначающий особое "пустое" значение?
например, Nothing для Maybe
точнее, мне надо обобщить Nothing и '\NUL'
семантика — отсутствие значения
кана
наверное его можно назвать терминальным, но я не уверен
а если его можно назвать еще и инициальным, то есть термин "нулевой"
Cheese
инициальный и терминальный подразумевает какое-то отношение, а у меня просто одно отдельное значение
Cheese
выколотое
Cheese
как non в линзах
Cheese
но Non, наверно, плохое название для класса
A64m
готовый класс в линзах и есть
A64m
но "пустое" значение оно не "выколотое" же, конструктор для него есть.