2011-10-10 4 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] 유형, 대신 classdata 사용, 당신은 Hackage에 대여섯 패키지에 구현되어

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

... 뭔가를 얻을. 대부분의 제공 적어도 :

  • 당신의 getIntStack/putIntStack 및 데이터 선언에서 직접 getBoolStack/putBoolStack
  • 가로 조성과 같은 투사 렌즈를 도출 할 수있는 능력 (첫 번째 렌즈, 다음 제 2 렌즈를 실행 - 첫 번째 예 다음 상기 WorldintStack) 및 수직 조성물 따기 약간 큰 구조 밖으로 World 따기 (한 쌍의 한쪽) State과 함께 StateT
  • 일부 인터페이스에서 병렬 개의 렌즈 각 실행 (예 : 당신이 [Bool] 또는 [Int]에 계산을 작성할 수 있으며이 World

에 계산 그래서 것처럼 그들을 실행 hackage을 확인 할 유형 Lens a b -> State b r -> State a r)의 무언가! a core, the deriving abilitythe stateful interface을 포함하는 data-lens 제품군이 있습니다. lens 패키지; 및 pointless-lenses 패키지. 아마 잊어 버린 것들도 있습니다.

+0

예. 렌즈를 발명했습니다. 지금 패키지를 hackage에서 꺼내고 있습니다. +1 – pat

+0

정말 고마워요. 얼마나 유용할까요? –

1

당신은 당신의 기능을 구현하기 위해 상태 모나드에서 푸시 팝 작업을 구현하고이를 사용할 수 있습니다

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')