Re[3]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 29.06.10 08:18
Оценка:
LCR>
L>>instance (l ~ r) => Boxed l r where
L>>    unwrap x = x
LCR>

LCR>Ибо такую синтаксическую конструкцыю я встречаю впервые.

Нашёл, магия под названием equality constraints, в статье "Type Checking with Open Type Functions"...
... << RSDN@Home 1.2.0 alpha 4 rev. 1423>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 29.06.10 08:18
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Это чего такое, можешь объяснить?


http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-families.html#id663186

Прикол в том, насколько я понимаю, что в случае

instance Boxed v v


унификация не проходит.

Например unwrap True не догадается сопоставить второй v с Bool.

Унификация возможна только в констрейнтах, поэтому мы выносим равенство типов в констрейнт

instance (l ~ r) => Boxed l r


По сути это эквивалентно первому инстансу, только теперь компилятор будет верно выводить типы.
Re[3]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: anton_t Россия  
Дата: 29.06.10 08:28
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>lomeo,


LCR>Это чего такое, можешь объяснить?

LCR>
L>>instance (l ~ r) => Boxed l r where
L>>    unwrap x = x
LCR>

LCR>Ибо такую синтаксическую конструкцыю я встречаю впервые.

Я так полагаю http://www.haskell.org/haskellwiki/GHC/Type_families , конкретно пункт 6.3.
Re[4]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 29.06.10 09:37
Оценка:
lomeo,

instance Boxed b v => Boxed (Box b) v where
    unwrap (Box x) = unwrap x

instance (l ~ r) => Boxed l r where
    unwrap x = x

А, то есть если b и v не совпадают (то есть когда мы находимся в середине цепочки вскрытия Box-ов), то будет использован первый инстанс (точнее, unwrap из первого инстанса), а когда l совпадает с r (то есть последнее, холостое вскрытие для конкретного 123), то будет использован второй инстанс. Правильно?
... << RSDN@Home 1.2.0 alpha 4 rev. 1423>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 29.06.10 09:39
Оценка:
anton_t,

_>Я так полагаю http://www.haskell.org/haskellwiki/GHC/Type_families , конкретно пункт 6.3.


Да, спасибо, из статьи как раз и вышел на семейства типов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1423>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 29.06.10 09:55
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR> Правильно?


Так точно!
Re[6]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 29.06.10 10:02
Оценка: :)
lomeo,

LCR>> Правильно?

L>Так точно!
Спасибо, брат!
... << RSDN@Home 1.2.0 alpha 4 rev. 1423>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: WolfHound  
Дата: 29.06.10 13:08
Оценка:
Здравствуйте, lomeo, Вы писали:

L>
L>instance Boxed b v => Boxed (Box b) v where
L>    unwrap (Box x) = unwrap x

L>instance (l ~ r) => Boxed l r where
L>    unwrap x = x
L>

Интересно но не понятно почему работает.
Дело в том что второй инстенс подходит для для всех типов и как следствие должна быть неоднозначность.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 29.06.10 14:48
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Интересно но не понятно почему работает.

WH>Дело в том что второй инстенс подходит для для всех типов и как следствие должна быть неоднозначность.

IncoherentInstances работают как OverlappingInstances.
Re[2]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Аноним  
Дата: 02.07.10 00:27
Оценка:
Здравствуйте, lomeo, Вы писали:

L>То, чем ты занимаешься, называется "извращение". Присоединюсь, если ты не против


Интересно, а вот такое можно как-нибудь без функциональных зависимостей заставить работать?
class Funct a b c d where
    f_map :: (a -> b) -> c -> d

instance (Functor m, Funct a b c d) => Funct a b (m c) (m d) where
    f_map = fmap . f_map

instance (a ~ c, b ~ d) => Funct a b c d where
    f_map = id
Re[3]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 02.07.10 10:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Интересно, а вот такое можно как-нибудь без функциональных зависимостей заставить работать?


А сейчас не работает? Можно пример?
Re[4]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Аноним  
Дата: 02.07.10 12:11
Оценка:
Здравствуйте, lomeo, Вы писали:

L>А сейчас не работает? Можно пример?


Неа:

f_map not [True]

<interactive>:1:0:
Couldn't match expected type `[Bool]' against inferred type `Bool'
When generalising the type(s) for `it'

Re[5]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: deniok Россия  
Дата: 02.07.10 22:28
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, deniok, Вы писали:


V>Интересная фича, но сдается мне, она возможна только если компилятор "видит" как формировался вложенный Box.


Да, но Simon Peyton Jones, похоже, взялся за суперкомпиляцию. Так что, возможно, GHC вскоре будет "видеть" довольно далеко.
Re[5]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 05.07.10 13:10
Оценка:
Здравствуйте, Аноним, Вы писали:

L>>А сейчас не работает? Можно пример?


А>Неа:


При явном указании типа работает. Если же явного указания нет, то мы ничего не сделаем. Тут такой прикол. Несмотря на ограничения инстанса GHC выбирает инстанс исходя только и исключительно из его заголовка — Fucnt a b c d или Funct a b (m c) (m d). Тут даже Overlapping(Incoherent)Instances не поможет. Я подумаю, что тут можно сделать, но, как мне кажется, лёгкого пути здесь нет.
Re[6]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Аноним  
Дата: 05.07.10 14:29
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Несмотря на ограничения инстанса GHC выбирает инстанс исходя только и исключительно из его заголовка — Fucnt a b c d или Funct a b (m c) (m d).


Что из заголовка, это понятно, но не понятно чем, в принципе отличаются:
instance (Functor m, Funct a b c d) => Funct a b (m c) (m d) where
    f_map = fmap . f_map

и
instance Boxed b v => Boxed (Box b) v where
    unwrap (Box x) = unwrap x


Почему для
f_map not [True]

выбирается, казалось бы, более общий случай
instance (a ~ c, b ~ d) => Funct a b c d where

а должен выбираться "more specific" (на мой взгляд — первый).
Re[7]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 06.07.10 06:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что из заголовка, это понятно, но не понятно чем, в принципе отличаются:

А>
А>instance (Functor m, Funct a b c d) => Funct a b (m c) (m d) where
А>    f_map = fmap . f_map
А>

А>и
А>
А>instance Boxed b v => Boxed (Box b) v where
А>    unwrap (Box x) = unwrap x
А>


У меня же явный тип указан.

А>Почему для

А>
А>f_map not [True]
А>

А>выбирается, казалось бы, более общий случай
А>
А>instance (a ~ c, b ~ d) => Funct a b c d where
А>

А>а должен выбираться "more specific" (на мой взгляд — первый).

More specific выбирается по шапке. a b c d ничем не хуже в этом случае, чем a b (m c) (m d), т.к. kind на специфичность не влияют.
Re[8]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Аноним  
Дата: 06.07.10 07:32
Оценка:
Здравствуйте, lomeo, Вы писали:

L>У меня же явный тип указан.


Box b?

L>More specific выбирается по шапке. a b c d ничем не хуже в этом случае, чем a b (m c) (m d), т.к. kind на специфичность не влияют.


"a b c d" и "a b [c] [d]" тоже одинаково специфичны?
class Funct a b c d where
    f_map :: (a -> b) -> c -> d

instance (Funct a b c d) => Funct a b [c] [d] where
    f_map = map . f_map

instance (a ~ c, b ~ d) => Funct a b c d where
    f_map = id
Re[9]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 06.07.10 17:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>"a b c d" и "a b [c] [d]" тоже одинаково специфичны?


Хм, спасибо.. Видимо я себе неправильно представлял выбор инстанса, либо баг в GHC.
Re[10]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: Аноним  
Дата: 06.07.10 18:02
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Хм, спасибо.. Видимо я себе неправильно представлял выбор инстанса, либо баг в GHC.


Не думаю что баг. Просто не так все тривиально как кажется (во всяком случае для меня).

Кстати, можно еще ваш пример вот так переписать, для наглядности:
data Box a = Box a

class Unboxable m where
    unbox :: m a -> a

instance Unboxable Box where
    unbox (Box a) = a

instance Unboxable [] where
    unbox [a] = a


class Boxed b v where
    unwrap :: b -> v

instance (Unboxable m, Boxed b v) => Boxed (m b) v where
    unwrap a = unwrap (unbox a)

instance (l ~ r) => Boxed l r where
    unwrap x = x

*Main> unwrap (Box [Box [[5]]])
5


PS А изначально-то вопрос взялся в результате медитирования вот над этим олеговским примером: deepest functor

Подозреваю, что "не тот инстанс" выбирается не из-за того, что оба одинаково "специфичны" (иначе бы было бы "Duplicate instance declarations"), а потому что "нужный" инстанс слишком специфичен (m d). А вот функциональными зависимостями это кажется чинится..
Re[11]: Этюд Unbox(Box<Box<...Box<T>...>> )
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 06.07.10 19:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, lomeo, Вы писали:


L>>Хм, спасибо.. Видимо я себе неправильно представлял выбор инстанса, либо баг в GHC.

А>Не думаю что баг. Просто не так все тривиально как кажется (во всяком случае для меня).

Угу. Всё таки я откопал
http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#instance-overlap

Suppose that from the RHS of f we get the constraint C Int [b]. But GHC does not commit to instance (C), because in a particular call of f, b might be instantiate to Int, in which case instance (D) would be more specific still. So GHC rejects the program. (If you add the flag -XIncoherentInstances, GHC will instead pick (C), without complaining about the problem of subsequent instantiations.)


Таким образом, если мы вместо OverlappingInstances используем IncoherentInstances, то GHC игнорирует следующую ошибку:

    Overlapping instances for Funct Bool Bool [Bool] d
      arising from a use of `f_map' at A.hs:12:14-29
    Matching instances:
      instance [overlap ok] (a ~ c, b ~ d) => Funct a b c d
        -- Defined at A.hs:9:9-39
      instance [overlap ok] (Funct a b c d) => Funct a b [c] [d]
        -- Defined at A.hs:6:9-44
    (The choice depends on the instantiation of `d'
     To pick the first instance above, use -XIncoherentInstances
     when compiling the other instance declarations)
    In the first argument of `print', namely `(f_map not [True])'
    In the expression: print (f_map not [True])
    In the definition of `main': main = print (f_map not [True])


Т.е. определить d надо явно для правильного выбора инстанса, потому что в одном случае (Bool) выберется один инстанс, как более специфичный, в другом ([Bool]) выберется другой. В моём случае с Boxed, видимо, мне просто повезло, что выбирался нужный инстанс — не знаю, тут надо подумать.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.