我想在Haskell中实现以下场景。我有一个定义如下的可枚举"事件"集:
data MyEvent = Event1
| Event2
| Event3
我想为这些事件定义处理程序,以以下方式使用:
eventLoop :: Handler h => h -> IO ()
eventLoop currentHandler = do
event <- getNextEvent
nextHandler <- currentHandler event
eventLoop nextHandler
基本上,我希望处理程序能够将自己或另一个处理程序返回到处理未来的事件。这是我不确定的处理程序类型。
我的第一个想法是将处理程序定义为简单的函数,但它们的类型获得无限长:
myHandler :: Event -> IO (Event -> IO (Event -> ... ))
我怀疑这可以通过一个类型类来解决,其中每个处理程序都需要实现一个处理事件的函数(该函数反过来返回另一种类型的相同的类),但是递归定义仍然适用。有人能更精通打字系统会给我指明正确的方向吗?我也欢迎对此有任何不同的看法。
谢谢!
嗯,"无限"类型通常相当于展开的递归类型。因此,您可以做的一件事是使用newtype
:使递归显式
newtype Handler = Handler { runHandler :: Event -> IO Handler }
这可能也是最简单的解决方案,因为它避免了为了获得不同的行为而篡改类型类和不同实例的需要——每个处理程序都可以选择它返回的内容,因为它们有一个统一的接口。
请注意,在许多情况下,定义一个类型类来解决这类问题是完全多余的。如果你处理的是多态类型Handler h => h
,那么你所能做的就是在它上面使用类型类的函数。如果在该类型类上定义的函数很简单,那么你可以通过概念上的"预应用"它们来省去很多麻烦。