Создайте функцию, похожую на threadDelay в Parsec - Haskell - PullRequest
0 голосов
/ 31 августа 2018

За последние несколько недель я создавал свой собственный язык Lisp-y с использованием Parsec в Haskell, следуя руководству «Напиши себе схему за 48 часов» . Обратите внимание, что я все еще новичок в Haskell.

Я пытаюсь реализовать функцию «сна», которая ждет определенное время, а затем выводит «true» после ввода команды в REPL, используя мои пользовательские типы из Parsec (я не использую лексер / токены) , Проблема в том, что когда я вводю функцию delay в REPL, она просто показывает «выполнено» вместо приостановки потока. Кроме того, я использую «Control.Monad.Error» вместо «Control.Monad.Except», потому что в учебнике используется ошибка.

Вот мои типы (сжатые для удобства):

-- All the custom data types, which follows the syntax: [Name - Haskell Type]
data Values = Atom String
         | Number Integer
         | InOut (IO ()) 
         | IOFunc ([Values] -> IOThrowsError Values) -- This is used for File and REPL IO

instance Show Values where show = showVal

Это моя функция "show" (сжатая для удобства):

showVal :: Values -> String
showVal (InOut _) = "done"
showVal (IOFunc _) = "<primitive>"

Наконец, функция:

import Control.Concurrent (threadDelay)

dTime :: [Values] -> IOThrowsError Values
dTime [Number n] = 
    let delay' = fromIntegral n
    in (return . InOut) (threadDelay delay')

Вывод REPL:

BuBBLE> (delay 1000) ; it works partially, but it immediately outputs `done`
done 

Работает ли threadDelay только в GHC или чего мне не хватает, чтобы заставить его работать?

Полный источник: Ninjacop / BuBBLE

1 Ответ

0 голосов
/ 31 августа 2018

dTime возвращает значение, которое содержит действие IO, которое, если вы его выполнили, приостановило бы поток. Хорошо. Но showVal никогда не пытается выполнить какой-либо IO - он просто видит «здесь есть IO действие», но ничего с этим не делает. На самом деле он не может ничего с этим сделать из-за чистой подписи -> String. Чтобы сделать его также и eval, вы, вероятно, захотите использовать evalString :: Env -> String -> IO String или что-то еще.

...