• ? Haskell typefun чего-то я совсем тупой стал.. есть:

    data F = A | B | C

    есть

    data M (a::F) = M (Ptr (M a))

    есть

    data SM = forall a . M a

    есть (по смыслу)

    typeOf :: SM -> F

    какой магией тепеь сделать case split по SM так чтобы было что-то вроде:

    case typeOf sm of
    A -> тут бы выводилось, что у нас M a

Replies (25)

  • @qnikst, а блин я ж такое уже писал ruhaskell.org :/
  • @qnikst, без синглтонов на вид не работает
  • @rufuse, ну естественно синглтоны или они же из палок и magic
  • @qnikst, так вообще если сделать data Tag (a::F) where TA :: Tag A ; TB :: Tag B .., то + class HasTag a where S a -> Tag a + data SM = forall a . HasTag a => SM a то должно взлететь
  • @qnikst, но это синглтоны без самой либы вроде
  • @qnikst, интересно насколько это быстро работать ещё будет т.к. очень узкое место. Или ну его нафиг и не выпендриваться?
  • @qnikst, ну в рамках капитана очевидности:
    — data M (a::F) = M (Ptr (M a)) без синглтонов не заселяется, но ты выше уже написал как можно на коленке
    — чтобы кейс сплит сделать, вероятно гадт нужен(а то и гадт с пруфами какими-то в констрейнтах)
  • @rufuse, у меня глаза уже в кучу, код сейчас не буду писать пробовать
  • @rufuse, data M = M (Ptr M) обычная штука для представления указателей приходящих из си. как вариант можно просто data M.
  • @qnikst, насчет производительности не скажу, но у меня почти по любому подобному вопросу нынче вердикт "не выпендриваться", т.к. на хаскелле подобные энкодинги становятся awkward'ными и неудобными очень быстро имхо, не агда все-таки
  • @rufuse, не, я бы выпендривался, если бы все это дело не убиралось в рамках одной фунции.
  • @qnikst, без типопараметра проще конечно, но тут задачу надо правильно понять сначала — тебе из внешней среды приходит что-то, по чему нужно сформировать значения разных типов?
  • @rufuse, где типов конечное множество и они могут тегом для другого
  • @rufuse, да, мне приходит struct foo { some_enum tag, union { .. }}, мне нужно в зависимости от того, что пришло вызвать нужный callback вытащив соотвествующее значение из union.
  • @qnikst, причем конвертация в haskell-ный тип не делается
  • @qnikst, у меня роутинг в сишке был, но на самом деле это плохо, толпа бойлерплейта и схалявили в одном месте, так что если правильно делать, то все равно нужно в haskell тащить
  • @qnikst, Если из юнион в хаскелле строчку получаешь — можно запилить два тайпкласса, один будет class M (u :: Symbol) a | u -> a, a -> u`, другой class ReduceM (a :: [*]) и у него два инстанса, один instance ReduceM '[], другой instance (M s a, ReduceM as, KnownSymbol s) => (a ': as) с нужными констрейнтами. В инстансе для (a ': as) делаешь symbolVal по `s` и сравниваешь с тем что из юниона пришло. Успех — возвращаешь что надо, неуспех — рекурсивно зовешь.
  • @rufuse, сорри что путанно, сонный уже
  • @rufuse, ну и потом в запускатор: run :: forall l … (ReduceM l) => Proxy l -> …
  • @rufuse, Ну KnownNat я могу прицепить, но чем это отличается то того что в 0 ?
  • @rufuse, мне больше импонирует case toSing s of но скорее всего я забью
  • @qnikst, отличается тем, что известно как делать сходу
  • @rufuse, и типопараметров ненужных меньше
  • @rufuse, да ну аккуратно делать, кода не меньше будет еще и классы неприятные
  • @qnikst, hackage.haskell.org есть еще такая штука