3

私はまだHaskellの初心者であり、今は頭がおかしいと思います。次のようなコードがあります。

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などを実装するデータ型を変更できるように構造化する方法がわかりません。

これがひどく漠然とした説明であることは知っていますが、上記のコードはおそらく絶対に間違った方法だと思います。

フィードバックをありがとう!

4

2 に答える 2

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/putIntStackおよびgetBoolStack/のような投影レンズを直接導出する機能putBoolStack
  • 水平方向の構図(最初に1つのレンズを実行し、次に2番目のレンズを実行します-たとえば、最初Worldにいくつかの大きな構造から取り出し、次にintStackから取り出しますWorld)および垂直方向の構図(2つのレンズを並列に実行し、それぞれがペアの片側にあります)
  • StateandとのインターフェースStateT(たとえば、タイプの何かLens a b -> State b r -> State a r)。これにより、またはで計算を記述し、それらをaでの計算である[Bool][Int]のように実行できます。World

だから、ハッキングをチェックしてください!コア派生能力、およびステートフルインターフェイスdata-lensを含むファミリがあります。レンズパッケージ; そして無意味なレンズパッケージ。おそらく私も忘れているものがあります。

于 2011-10-10T13:48:37.167 に答える
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')
于 2011-10-10T11:52:55.727 に答える