metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2013-01-08 07:33 pm
Entry tags:

Знаете ли вы, что

Scala - это Haskell в жабьей шкуре?

Если кложура сразу видна как лисп и не совсем мейнстримный язык, то скала замаскирована жабьей шкуркой от зоркого ока менеджеров, чтобы к тому времени, как до них дойдет, во что они вляпались - было уже поздно.

Язык знатно безумный, я почти Programming in Scala дочитал. И кое-какие вещи там сильно похожи на решение некоторых проблем с наследованием и зависимостями типов друг от друга, которых мне не хватало в дельфи и дотнетах :)

[identity profile] isorecursive.livejournal.com 2013-01-14 02:38 am (UTC)(link)
@ Это неверный Haskell.
Хорошо, вот:
{-# 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 ()
Edited 2013-01-14 05:16 (UTC)

[identity profile] thesz.livejournal.com 2013-01-15 01:57 am (UTC)(link)
У вас снова неправильный Хаскель.

Моё решение, когда я обнаружил ошибку:
{-# 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))
Интересно, найдёте ли вы ошибку в своём коде?

[identity profile] isorecursive.livejournal.com 2013-01-15 11:54 pm (UTC)(link)
@ App :: (a :-> b) -> a -> Term b
А подразумевал
App :: (a :-> b) -> Term a -> Term b

, конечно.

@ class MkT a
@ b <- mkTerm
@ ...
Пока не представляю, что Вы хотели этим показать. С inventVar всё понятно - это такой gensym в state-монаде,
а вот mkTerm - это какой-то конструктор канонических термов для заданных типов.
Непонятно, как он поможет погружать хаскельные лямбда-абстракции в лямбда-абстракции подъязыка.
Даже пофантазировать на эту тему особо не получается, потому что ясно, что, например, для типа Double,
mkTerm будет возвращать какой-то один и тот же терм. Как, например, это соотносится с
test $ \x -> add x 0.5 -- > outputs Abs (Var "x") (Sum (Var "x") (Num 0.5))
test $ \x -> add (add x 0.5) 0.5 -- >  outputs Abs (Var "x") (Sum (Sum (Var "x") (Num 0.5)) (Num 0.5))

?
Похоже, что этот вот "MkT b => MkT (a -> b)" в "b <- mkTerm" вообще опирается исключительно на тип тела лямбда-абстракции. Как он будет погружать тело хаскельной лямбда-абстракции в подъязык, если он даже ничего о нём кроме типа не осознаёт? Для одного только типа тела Double у нас бесконечно разных термов, которые мы хотели бы погрузить в разные термы подъязыка.

[identity profile] thesz.livejournal.com 2013-01-15 11:55 pm (UTC)(link)
У вас и в test неправильная сигнатура.

[identity profile] isorecursive.livejournal.com 2013-01-16 12:58 am (UTC)(link)
Решить другую задачу и сказать, что постановщик ошибся в условии. Каков трюк!

[identity profile] thesz.livejournal.com 2013-01-16 12:59 am (UTC)(link)
Ничем не могу помочь.