我在理解如何处理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个方法(但具有不同的实现),并且还可以具有一些内部状态(相互比较时非常不同)。
答案 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) -> ...