Подтвердить что ты не робот

Насколько практично внедрять ядро ​​языка с эффективным функциональным пространством (например, ML) в Haskell?

Как предложил Могги 20 лет назад эффективное функциональное пространство -> таких языков, как ML, можно разложить в стандартное полное функциональное пространство => плюс сильную монаду T для захвата эффектов.

A -> B разлагается на A => (T B)

Теперь Haskell поддерживает монады, в том числе монаду IO, которая кажется достаточной для эффектов в ML, и имеет пространство функций, которое содержит = > (но также включает в себя частичные функции). Таким образом, мы должны иметь возможность перевести значительный фрагмент ML в Haskell через это разложение. В теории я думаю, что это работает.

Мой вопрос заключается в том, может ли такое встраивание быть практичным: возможно ли создать библиотеку Haskell, которая позволяет программировать в Haskell в стиле, не слишком далеком от ML? И если да, то как будет производиться?

Мои критерии "практического" заключаются в том, что существующий код ML с широким использованием эффектов может быть относительно легко транскрибирован в Haskell посредством внедрения, включая сложные случаи, связанные с функциями более высокого порядка.

Чтобы сделать это конкретным, моя собственная попытка такой транскрипции через встраивание ниже. Основная функция - транскрипция некоторого простого кода ML, который императивно генерирует 5 различных имен переменных. Вместо того, чтобы напрямую использовать декомпозицию, моя версия поднимает функции так, чтобы они оценивали свои аргументы - определения до main представляют собой мини-библиотеку, включающую отмененные примитивы. Это работает нормально, но некоторые аспекты не являются полностью удовлетворительными.

  • Здесь слишком много синтаксического шума для ввода значений в вычисления через val. Если бы разблокированные версии функций (например, rdV) помогли бы этому, ценой необходимости их определения.
  • Необязательные определения типа varNum требуют монадического связывания через <- в do. Затем это заставляет любые определения, зависящие от них, также находиться в одном выражении do.
  • Кажется, что вся программа может оказаться в одном огромном выражении do. Это то, как часто рассматриваются программы ML, но в Haskell это не совсем так хорошо поддерживается - например, вы вынуждены использовать case вместо уравнений.
  • Я думаю, что будет какая-то ленивость, несмотря на то, что она навешивает монаду IO. Учитывая, что программа ML будет разработана для проведения строгой оценки, следует, вероятно, удалить лени. Я не уверен, что лучший способ сделать это, хотя.

Итак, какие-либо советы по улучшению этого, или по лучшим подходам, использующим ту же самую декомпозицию, или даже совершенно разные способы достижения такой же широкой цели программирования в Haskell с использованием стиля, который отражает ML? (Это не то, что мне не нравится стиль Haskell, это просто то, что я хотел бы легко сопоставить существующий код ML.)

import Data.IORef
import Control.Monad

val :: Monad m => a -> m a
val = return

ref = join . liftM newIORef
rdV = readIORef                                    -- Unlifted, hence takes a value
(!=) r x =  do { rr <- r; xx <- x; writeIORef rr xx  }

(.+),(.-) :: IO Int -> IO Int -> IO Int
( (.+),(.-) ) = ( liftM2(+), liftM2(-) )

(.:) :: IO a -> IO [a] -> IO [a]
(.:) = liftM2(:)
showIO :: Show a => IO a -> IO String
showIO = liftM show

main = do 
    varNum <- ref (val 0)
    let newVar = (=<<) $ \() -> val varNum != (rdV varNum .+ val 1) >> 
                                val 'v' .: (showIO (rdV varNum))
    let gen = (=<<) $ \n -> case n of 0 -> return []
                                      nn -> (newVar $ val ()) .: (gen (val n .- val 1))
    gen (val 5)
4b9b3361

Ответ 1

Здесь возможный путь, по sigfpe. Он не охватывает лямбда, но, похоже, он может быть распространен на них.