要将IO函数添加到用Haskell编写的编程语言解释器中,我基本上有两个选项:
unsafePerformIO
。前者对我来说是一个坏主意 - 这有效地否定了任何纯度的好处,让IO
几乎到达程序的任何地方。我目前也大量使用ST
,并且必须修改大量的程序才能实现这一点,因为我无法同时使用ST
和IO
时间(?)。
后者让我感到紧张 - 正如函数名称所述, 不安全,但我认为在这种情况下它可能是合理的。特别:
seq
,可以明确对可以执行IO的点进行排序。unsafePerformIO
的每个函数。在这种情况下,是否有充分理由不使用unsafePerformIO
?
答案 0 :(得分:2)
如果我理解正确,你想将IO
动作添加到解释语言(不纯的初学者),而解释器本身是纯粹的。
第一个选项是来自解释器的抽象primops。例如,解释器可以在一些未指定的monad中运行,而priops被注入:
data Primops m = Primops
{ putChar :: Char -> m ()
, getChar :: m Char
, ...
}
interpret :: Monad m => Primops m -> Program -> m ()
现在解释器不能执行任何IO
操作,除了封闭的primops列表。 (您可以使用自定义monad实现类似的结果,而不是将primops作为参数传递。)
但是,在你确切地说出为什么需要纯粹的翻译之前,我认为它过度工程化了。可能你不是吗?如果您只是想让解释器的纯部分易于测试,那么最好将这些部分提取到单独的纯函数中。这样,顶级入口点将是不纯的,但很小,但所有解释器的逻辑都是可测试的。