Знаете ли вы, что
Jan. 8th, 2013 07:33 pmScala - это Haskell в жабьей шкуре?
Если кложура сразу видна как лисп и не совсем мейнстримный язык, то скала замаскирована жабьей шкуркой от зоркого ока менеджеров, чтобы к тому времени, как до них дойдет, во что они вляпались - было уже поздно.
Язык знатно безумный, я почти Programming in Scala дочитал. И кое-какие вещи там сильно похожи на решение некоторых проблем с наследованием и зависимостями типов друг от друга, которых мне не хватало в дельфи и дотнетах :)
Если кложура сразу видна как лисп и не совсем мейнстримный язык, то скала замаскирована жабьей шкуркой от зоркого ока менеджеров, чтобы к тому времени, как до них дойдет, во что они вляпались - было уже поздно.
Язык знатно безумный, я почти Programming in Scala дочитал. И кое-какие вещи там сильно похожи на решение некоторых проблем с наследованием и зависимостями типов друг от друга, которых мне не хватало в дельфи и дотнетах :)
no subject
Date: 2013-01-14 01:39 am (UTC)Вообще-то, именно их и называют EDSL. Это синонимы.
Если мы повторяем синтаксис стороннего языка в языке носителе, то это называется EDSL. Так уж получилось, что применение функций и абстрагирование позволяет повторить (с точностью до синтаксических преобразований) синтаксис многих других языков.
Термин появился задолго до того, как вы стали изучать Scala. Я столкнулся с ним в 1999-ом, в контексте комбинаторов синтаксического разбора.
>Вот, смотрите:
Я не могу это читать. У меня голова по-другому работает. Я не для того решил в 1998 году уйти от объектов и наследований, чтобы возвращаться обратно.
Дайте мне алгебраическую структуру и я счастлив.
>А как они помогут пронаблюдать имя переменной лямбды и имена свободных термов?
Применением.
instance (B a, G b) => G (a -> b) where dadam f = do a <- inventArg b <- applyG f a dadam bПримерно так.Внутри функции f будут известны её параметры, как переменные.
См. также REPA и Accelerate.
no subject
Date: 2013-01-14 02:09 am (UTC)Вот же:
На хаскеле это будет что-то такое:
{-# LANGUAGE GADTs #-} data Term :: * -> * where Num :: Double -> Term Double Sum :: Term Double -> Term Double -> Term Double ... type (a ~> b) = Term (a -> b)@ Применением.
Просто так по этому коду трудно понять, о чём речь. Где-нибудь можно посмотреть определение B, G, applyG?
Это не hoas хоть какой-нибудь? Речь же о том, чтобы иметь возможность делать произвольные биндеры, а с hoas получится, что если мы хотим какие-то другие, то нам надо сделать 2 подъязыка - первый - просто чтобы пронаблюдать переменные и оттранслировать лямбда-абстракции во второй. И ещё первый будет накладывать существенные ограничения на синтаксис подъязыка и на взаимодействие с хост-языком. Если получится, что любая лямбда-абстракция, которую мы хотим оттранслировать в конечный подъязык, на уровне хаскеля должна быть типа (SomeVarType -> SomeTermType), то это неприкольно, если нам хочется внутри её заиспользовать так, будто у неё её честный тип.
no subject
Date: 2013-01-14 02:20 am (UTC)>На хаскеле это будет что-то такое: > >{-# LANGUAGE GADTs #-} > >data Term :: * -> * where > Num :: Double -> Term Double > Sum :: Term Double -> Term Double -> Term Double > ... > >type (a ~> b) = Term (a -> b)Это неверный Haskell.> Где-нибудь можно посмотреть определение B, G, applyG?
Я предложил посмотреть на REPA и Accelerate. Там хорошо показана эта техника.
>Если получится, что любая лямбда-абстракция, которую мы хотим оттранслировать в конечный подъязык, на уровне хаскеля должна быть типа (SomeVarType -> SomeTermType), то это неприкольно, если нам хочется внутри её заиспользовать так, будто у неё её честный тип.
Я не понимаю, о чём здесь идёт речь.
no subject
Date: 2013-01-14 02:38 am (UTC)Хорошо, вот:
{-# LANGUAGE GADTs, KindSignatures, TypeOperators, UnicodeSyntax #-} import Prelude.Unicode type (a :→ b) = Term (a → b) data Term ∷ * → * where Num ∷ Double → Term Double Sum ∷ Term Double → Term Double → Term Double Var ∷ String → Term a Abs ∷ Term a → Term b → a :→ b App ∷ (a :→ b) → a → Term b add = Sum test ∷ (a → b) → IO () test = undefined -- main = test $ \x → add x 0.5 -- Abs (Var "x") (Sum (Var "x") (Num 0.5))Чтобы получился эквивалент того, что я продемонстрировал на Scala, нужно написать такое определение test, которое будет выводить для описанного применения main описанный вывод. Если заменить в двух закомментированных строчках x на y, предыдущее требование также должно исполняться.
@ Я предложил посмотреть на REPA и Accelerate. Там хорошо показана эта техника.
Уже начал смотреть, но пока не нашёл.
@ Я не понимаю, о чём здесь идёт речь.
Нужно, чтобы в теле лямда-абстракции, к которой апплицируется test, аргумент был доступен с типом a (см. сигнатуру test), а не с каким-нибудь HoasBinderVarType.
UPD:
Вот здесь "Если заменить в двух закомментированных строчках x на y, предыдущее требование также должно исполняться." я перестарался. С точностью до альфа-конвертируемости будет fine enought. Просто я хотел сказать, что test _ = putStr "Abs (Var "x") (Sum (Var "x") (Num 0.5))" - не подходит, но неправильно сформулировал.
UPD2: test ∷ (a :→ b) → IO ()
no subject
Date: 2013-01-15 01:57 am (UTC)Моё решение, когда я обнаружил ошибку:
{-# LANGUAGE GADTs, KindSignatures, TypeOperators, UnicodeSyntax #-} --import Prelude.Unicode import Control.Monad.State type (a :-> b) = Term (a -> b) data Term :: * -> * where Num :: Double -> Term Double Sum :: Term Double -> Term Double -> Term Double Var :: String -> Term a Abs :: Term a -> Term b -> a :-> b App :: (a :-> b) -> a -> Term b add = Sum type MkTerm a = State Int a class MkT a where mkTerm :: MkTerm (Term a) inventVar :: MkTerm (Term a) inventVar = do modify (+1) x <- get return $ Var $ "x"++show x instance MkT b => MkT (a -> b) where mkTerm = do a <- inventVar b <- mkTerm return $ Abs a b tyoe family ToTerm a type instance ToTerm test ∷ (a -> b) -> IO () test = undefined -- main = test $ \x -> add x 0.5 -- Abs (Var "x") (Sum (Var "x") (Num 0.5))Интересно, найдёте ли вы ошибку в своём коде?no subject
Date: 2013-01-15 11:54 pm (UTC)А подразумевал
, конечно.
@ class MkT a
@ b <- mkTerm
@ ...
Пока не представляю, что Вы хотели этим показать. С inventVar всё понятно - это такой gensym в state-монаде,
а вот mkTerm - это какой-то конструктор канонических термов для заданных типов.
Непонятно, как он поможет погружать хаскельные лямбда-абстракции в лямбда-абстракции подъязыка.
Даже пофантазировать на эту тему особо не получается, потому что ясно, что, например, для типа Double,
mkTerm будет возвращать какой-то один и тот же терм. Как, например, это соотносится с
?
Похоже, что этот вот "MkT b => MkT (a -> b)" в "b <- mkTerm" вообще опирается исключительно на тип тела лямбда-абстракции. Как он будет погружать тело хаскельной лямбда-абстракции в подъязык, если он даже ничего о нём кроме типа не осознаёт? Для одного только типа тела Double у нас бесконечно разных термов, которые мы хотели бы погрузить в разные термы подъязыка.
no subject
Date: 2013-01-15 11:55 pm (UTC)no subject
Date: 2013-01-16 12:58 am (UTC)no subject
Date: 2013-01-16 12:59 am (UTC)