私は関数型プログラミングの初心者で、最近 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です
「ライター」コンストラクターの代わりに「ライター」と呼ばれる関数が使用可能になります。変化する:
logNumber x = Writer (x, ["Got number: " ++ show x])
に:
logNumber x = writer (x, ["Got number: " ++ show x])
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)