2011-10-10 41 views
3

我仍然是哈斯克尔的新手,我认为我现在已经过了头。我的代码如下所示。复杂状态单体结构

data World = World { 
    intStack :: [Int], 
    boolStack :: [Bool] 
} deriving Show 

instance IntStack World where 
    getIntStack = intStack 
    putIntStack ints (World _ bools) = World ints bools 

instance BoolStack World where 
    getBoolStack = boolStack 
    putBoolStack bools (World ints _) = World ints bools 

class IntStack a where 
    getIntStack :: a -> [Int] 
    putIntStack :: [Int] -> a -> a 

class BoolStack a where 
    getBoolStack :: a -> [Bool] 
    putBoolStack :: [Bool] -> a -> a 

(<=>) :: (IntStack c, BoolStack c) => c -> c 
(<=>) w = putIntStack xs . putBoolStack ((x == x'):bs) $ w 
    where (x:x':xs) = getIntStack w 
      bs = getBoolStack w 

(<+>) :: (IntStack c) => c -> c 
(<+>) w = putIntStack ((x+x'):xs) w 
    where (x:x':xs) = getIntStack w 

我的焦点(目前忽略的功能的错误情况)是能够链接在一起的功能,如(< =>)和(< +>)假设底层数据类型实现了功能的必需的接口。

我觉得我可以打扫一下了很多有状态单子,但我不知道如何构建它允许更改实现IntStack,BoolStack等任何数据类型..

我知道这是一个非常模糊的描述,但我觉得我上面的代码可能是完全错误的方法。

感谢您的任何反馈!

回答

5
class IntStack a where 
    getIntStack :: a -> [Int] 
    putIntStack :: [Int] -> a -> a 

class BoolStack a where 
    getBoolStack :: a -> [Bool] 
    putBoolStack :: [Bool] -> a -> a 

恭喜你,你已经发明了镜头!摘要[Int][Bool]类型,并使用data代替class,和你喜欢的东西

data Lens a b = Lens 
    { get :: a -> b 
    , put :: b -> a -> a 
    } 

...这是在半打包上实现Hackage。大多数提供至少:

  • 导出像您的getIntStack/putIntStackgetBoolStack /直接从数据声明putBoolStack
  • 水平构图的投影透镜的能力(第一运行一个透镜,则第二透镜 - 例如,第一采摘World出一些较大的结构,然后采摘intStackWorld的)和垂直组合物(在一对的一侧)
  • StateStateT一些接口并行运行的两个透镜,每个(例如什么类型Lens a b -> State b r -> State a r),这将让你写计算上[Bool][Int]并运行它们,就好像他们是在一个World

计算所以,检查出hackage!有data-lens系列,其中包括a corethe deriving abilitythe stateful interface; lens包;和pointless-lenses包。有可能我也忘了一些。

+0

耶,我也(重新)发明了镜头!我现在正在从hackage中拉出软件包。 +1 – pat

+0

非常感谢,绝对让我感到有用的是这些。 –

1

您可以实现在状态单子push和pop操作,并利用它们来实现你的功能:

popInt :: IntStack c => State c Int 
popInt = do 
    (x:xs) <- getIntStack <$> get 
    modify $ putIntStack xs 
    return x 

pushInt :: IntStack c => Int -> State c() 
pushInt x = do 
    xs <- getIntStack <$> get 
    modify $ putIntStack (x:xs) 

(<+>) :: IntStack c => State c() 
(<+>) = do 
    x <- popInt 
    x' <- popInt 
    pushInt (x + x')