Как предложил Могги 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)