web-dev-qa-db-ja.com

HaskellでControl.Monad.Writerを使用する方法

私は関数型プログラミングの初心者で、最近 Learn You a Haskell で学習しましたが、 この章 を経て、以下のプログラムにこだわった:

import Control.Monad.Writer  

logNumber :: Int -> Writer [String] Int  
logNumber x = Writer (x, ["Got number: " ++ show x])  

multWithLog :: Writer [String] Int  
multWithLog = do  
    a <- logNumber 3  
    b <- logNumber 5  
    return (a*b)

これらの行を.hsファイルに保存しましたが、ghciにインポートできず、不満がありました。

more1.hs:4:15:
    Not in scope: data constructor `Writer'
    Perhaps you meant `WriterT' (imported from Control.Monad.Writer)
Failed, modules loaded: none.

「:info」コマンドでタイプを調べました。

Prelude Control.Monad.Writer> :info Writer
type Writer w = WriterT w Data.Functor.Identity.Identity
               -- Defined in `Control.Monad.Trans.Writer.Lazy'

私の観点からは、これは「newtype Writer w a ...」のようなものであると想定されていたため、データコンストラクターにデータを供給してWriterを取得する方法について混乱しています。

バージョン関連の問題である可能性があり、ghciのバージョンは7.4.1です

86
Javran

「ライター」コンストラクターの代わりに「ライター」と呼ばれる関数が使用可能になります。変化する:

logNumber x = Writer (x, ["Got number: " ++ show x])

に:

logNumber x = writer (x, ["Got number: " ++ show x])

5
Marcus

LYAHを試してみると同様のメッセージが表示されました "For a some Monads More"repl.it でオンラインHaskellエディターを使用

インポートを次から変更しました:

import Control.Monad.Writer

に:

import qualified Control.Monad.Trans.Writer.Lazy as W

そのため、私のコードは次のように動作します( Kwang's Haskell Blog からのインスピレーションにより):

import Data.Monoid
import qualified Control.Monad.Trans.Writer.Lazy as W


output :: String -> W.Writer [String] ()
output x = W.tell [x]


gcd' :: Int -> Int -> W.Writer [String] Int  
gcd' a b  
    | b == 0 = do  
        output ("Finished with " ++ show a)
        return a  
    | otherwise = do  
        output (show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b))
        gcd' b (a `mod` b)

main :: IO()
main = mapM_ putStrLn $ snd $ W.runWriter (gcd' 8 3) 

コードは現在ここで実行可能です

1