2012-01-31 13 views
3

私はこの問題に取り組んでおり、これまでに関連する質問をしていました。 Implementation of State Monad私のコードをさらに洗練するために、私は1つの増分関数を使って実装しようとしました。状態モナド例問題

module StateExample where 
import Control.Monad.State 

data GlobState = GlobState { c1 :: Int, c2:: Int, c3:: Int} deriving (Show) 

newGlobState:: GlobState 
newGlobState = GlobState { c1=0,c2=0,c3=0 } 

incr :: String-> State GlobState() 
incr x = do 
    modify(\g -> g {x =x g + 1}) 

main:: IO() 
main = do 
    let a1= flip execState newGlobState $ do 
     incr c1 
     incr c2 
     incr c1 
    print a 

しかし、ここで私はエラー私はこのエラーを削除するにはどうすればよい

`x' is not a (visible) constructor field name 

取得していますか?

答えて

8

あなたはHaskellの弱点を打ちました:レコードはファーストクラスの値ではありません! 実際、これまでと同じように書くのは非常にいいですが、不可能です。 ただし、さまざまなライブラリを使用して目的の効果を得ることができます。 これは fclabelsを使用している場合、それがどのように見えるかです:

{-# LANGUAGE TemplateHaskell, TypeOperators #-} 
module StateExample where 

import Control.Monad.State hiding (modify) 
import Data.Label (mkLabels) 
import Data.Label.Pure ((:->)) 
import Data.Label.PureM 

data GlobState = GlobState { _c1 :: Int , _c2 :: Int , _c3 :: Int } deriving Show 
$(mkLabels [''GlobState]) 

newGlobState:: GlobState 
newGlobState = GlobState { _c1 = 0, _c2 = 0, _c3 = 0 } 

incr :: (GlobState :-> Int) -> State GlobState() 
incr x = modify x (+1) 

main :: IO() 
main = do 
    let a = flip execState newGlobState $ do 
     incr c1 
     incr c2 
     incr c1 
    print a 

いくつかの魔法の部分がここにあります。同じ のレコード名を持つが、先頭にアンダースコアを付けると、GlobStateと定義されます。次に、関数 mkLabelsは、TemplateHaskellを使用して、レコード内のすべてのフィールド に「レンズ」を定義します。これらのレンズは同じ名前ですが、アンダースコアはありません。引数(GlobState :-> Int)incrは、 レンズです。の機能はData.Label.PureM です。このモードでは、このように定義されたレコードが状態モナド内で更新されます。衝突を避けるため、 modifyControl.Monad.Stateから隠します。

あなたは getsputsとして、状態モナドで使用可能な他の機能のために documentation for PureM に他の の機能を見ることができます。

あなたはfclabelsがインストールされていませんが、あなたは(あなたがHaskellのプラットフォームをインストールする場合は、あなたが得る)cabal-installパッケージからcabal実行可能ファイルを持っている場合、あなたは、単に実行してfclabelsをインストールすることができます。

cabal install fclabels 

の場合最初にcabalを実行するときは、まずデータベースを更新する必要があります。

cabal update 
+0

モジュールData.Label.PureMはライブラリにありません。どのように私はそれをインストールするのですか? –

+0

'fclabels'をインストールするためのいくつかの指示で私の答えを更新しました。これはCabalで' Data.Label.PureM'を提供します。 – danr

+1

レンズ(または "ラベル"またはあなたがそれらを呼びたいもの)のための完全なセールスポイントは、 –

関連する問題