在Haskell中使用类似接口的方式苦苦挣扎

时间:2014-10-08 10:53:17

标签: haskell interface

我在理解如何处理Haskell中的方法之类的接口时遇到了问题。如果在OOP术语中考虑它,那么我希望有不同的对象实现相同的接口(只是几种方法)并跟踪一些内部状态。

我从一些类型类开始

class FileTransformer where
    doThis :: a -> b -> c
    doThat :: d -> e -> f

虽然如果我要创建不同的数据类型,如

data FirstThingy = FirstThingy { internalState :: STRef s Int } -- simplified
data SecondThingy = SecondThingy { differentState :: STRef s Word8 } -- simplified

instance FileTransformer FirstThingy where
    doThis = ... -- does some stuff with internal state also
    doThat = ... -- does some stuff with internal state also

-- implementation of doThis and doThat is different from the above one
instance FileTransformer SecondThingy where
    doThis = ... -- does some stuff with internal state also
    doThat = ... -- does some stuff with internal state also

然后我会做这样的事情就足够了:

firstThingy = FirstThingy someInitialState
secondThingy = SecondThingy someOtherInitialState

loadFileTransformer :: FileTransformer ft => FileHeader -> ft
loadFileTransformer header = if simple header then firstThingy else secondThingy

但是,你可能已经猜到这不起作用......

所以,问题是Haskell中的方法是什么,允许我根据某些特定需求选择不同的文件转换器?每个变换器必须有2个方法(但具有不同的实现),并且还可以具有一些内部状态(相互比较时非常不同)。

2 个答案:

答案 0 :(得分:2)

您可能需要考虑使用ADT来代表Thingy,而不是两种单独的类型:

data Thingy = FirstThingy (STRef s Int) | SecondThingy (STRef s Word8)

然后你可以在Thingy上进行模式匹配:

doThis :: Thingy -> a -> b -> c
doThis (FirstThingy st) = ...
doThis (SecondThingy st) = ...

doThat类似。然后你的最后一个代码块看起来像这样:

firstThingy = FirstThingy someInitialState
secondThingy = SecondThingy someOtherInitialState

loadFileTransformer :: FileHeader -> Thingy
loadFileTransformer header
    | simple header = firstThingy
    | otherwise = secondThingy

答案 1 :(得分:1)

您可能只想使用合适的参数调用函数,而不是尝试使用表示不同文件转换的内部状态创建对象

如果不了解您的变压器的使用方式,很难确切地说明如何最好地构建变压器。但是,如果你有一个doTheStuff函数想要一个"变换器对象"作为输入,为什么不采取两种方法"作为参数,以及初始状态值?

doTheStuff :: state -> (state -> a -> b -> c) -> (state -> d -> e -> f) -> ...