在RWS monad中解释免费的Teletype monad

时间:2018-10-18 22:23:53

标签: haskell free-monad

我目前正在学习免费的monad,我正在尝试使用其中最简单,最常见的示例– Teletype

{-# LANGUAGE DeriveFunctor #-}

import Control.Monad.Free

data TeletypeF a = Put String a
                 | Get (String -> a)
    deriving Functor

type Teletype = Free TeletypeF

许多教程解释了Teletype单子程序中的IO程序。例如:

-- Utilities
get   = liftF $ Get id
put s = liftF $ Put s ()

-- Sample programs
echo :: Teletype ()
echo = do word <- get
          if word == "\04"  -- Ctrl-D
          then return ()
          else put word >> echo

hello :: Teletype ()
hello = do put "What is your name?"
           name <- get
           put "What is your age?"
           age <- get
           put ("Hello, " ++ name ++ "!")
           put ("You are " ++ age ++ " years old!")

-- Interpret to IO
interpIO :: Teletype a -> IO a
interpIO = foldFree lift
    where
        lift (Put s a) = putStrLn s >> return a
        lift (Get f)   = getLine >>= return . f

我试图用另一种monad来解释它,即RWS monad。 这个想法是受this assignment上一次练习的启发。 我正在使用RWS数据类型从Reader部分获取输入,并在State部分中累积输出。 但是,不幸的是,我无法使其正常运行。到目前为止,这是我的尝试:

import Control.Monad.Trans.RWS.Lazy hiding (get, put)

type TeletypeRWS = RWS [String] () [String]

-- Interpret to TeletypeRWS
interpRWS :: Teletype a -> TeletypeRWS a
interpRWS = foldFree lift
    where
        lift (Put s a) = state (\t -> ((), t ++ [s])) >> return a
        lift (Get f)   = reader head >>= local tail . return . f  -- This is wrong

mockConsole :: Teletype a -> [String] -> (a, [String])
mockConsole p inp = (a, s)
    where
        (a, s, _) = runRWS (interpRWS p) inp []

运行TeletypeRWS“程序”时,不会删除环境中的第一个值:

*Main> mockConsole hello ["john", "18"]
((),["What is your name?","What is your age?","Hello, john!","You are john years old!"])

我对更新Reader有点不安,但是我不知道如何才能访问列表中的下一个值。 TeletypeRWS的类型是根据上述练习选择的,因此我认为应该可以实现interpRWS

1 个答案:

答案 0 :(得分:2)

我们不能使用 'use strict'; describe('Test Controller', function () { var _myModalCtrl, _title, _scope; var _modalInstance; beforeEach(function () { module('myApp'); inject(function ($controller, $rootScope) { _scope = $rootScope.$new(); _modalInstance = {close: function () { }}; _title = { }; _myModalCtrl = $controller('myModalCtrl', { $scope: _scope, $uibModalInstance: _modalInstance, title: _title, }); }); }); describe('Functions', function() { it('Submit', function () { _scope.updateFiles(); --> ** This is failing ** }); it('Cancel', function () { _scope.cancel(); }); }); :在延续中它必须是参数化的,因此我们不能在此处应用foldFree。相比之下,local显式地为我们提供了实际的延续而无需泛化,因此可以使用。

iterM