如何调用部分非巢式变压器?

时间:2016-03-26 23:09:43

标签: haskell monads monad-transformers

鉴于变换器:: T2 of T1 of M0的嵌套,我如何利用:: T2 of M0:: M2

这是一个例子:我正在编写一些需要读取,记录和状态的函数。定义:

gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM

如果我想打个电话  stateFunction :: State Viable NUM

甚至是stateWithReaderFunction :: ReaderT Env (State Viable) NUM

我可以使用lift

gameRoutine = do
    x <- lift . lift $ stateFunction
    y <- lift $ stateWithReaderFunction

但我如何致电writerFunction :: Writer [String] a

如何致电writerStateFunction :: WriterT [String] (State Viable) NUMgameRoutine定义之间的差异为ReaderT图层缺失?)

显然,我不想将其定义提升为gameRoutine之一。

2 个答案:

答案 0 :(得分:5)

嗯,基本上mtl的想法是你需要这样做。您可以使用通用签名

来定义writerStateFunction,而不是使用该特定签名定义writerStateFunction' :: (MonadWriter [String] m, MonadState Viable m) => m NUM
Reader

然后,尝试使用此环境的环境有一个额外的MonadWriter图层并不重要:这不会阻止monad同时拥有MonadState<html> <head> <title>Example</title> </head> <script src='https://www.google.com/recaptcha/api.js'></script> <script> //This is our DOM on JQUERY or JAVASCRIPT named as main.js $(function() { //First we have to listen on a event click (button) and extract the values of the inputs $('body').on('click','.myButtonClass', function() { $email = $('#emailID').val(); $password = $('#passwordID').val(); $recaptcha = $('textarea').val(); //We save in a object our values $x = { action:'validate', email:$email, password:$password captcha:$recaptcha }; //We execute ajax calling a php file for POST method $.post('file.php',$x,function(callback) { $('.answer').html(callback); }); }); }); /*END OF DOM AND MAIN.JS*/ </script> <body> <form> <input type="email" id="emailID" placeholder="Write here your email"> <input type="password" id="passwordID" placeholder="Write here your password"> <input type="button" class="myButtonClass"> </form> <!--Your div recaptcha. This give you the page recaptcha google when you are into your configuration Change the XXXX for your SITE KEY numbers and letters --> <div class="g-recaptcha" data-sitekey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"></div> <!--This will be where we display the answer with ajax, in the element who have the class answer--> <div class="answer"></div> </body> </html> <?php //this is your file.php require_once 'recaptchalib.php'; //BEGIN OUR PHP FILE WHERE WE'LL RECIEVE ALL THE DATA FROM THE AJAX FILE //we save the action sended trough ajax $action = $_POST['action']; if ( $action == 'validate' ) : //WE SAVE A EMAIL $email = addslashes($_POST['email']); //WE SAVE THE PASSWORD FOR THIS EXAMPLE $password = addslashes($_POST['password']); //We paste here one more time our secret key $secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; $response = null; $reCaptcha = new ReCaptcha($secret); $captcha = $_POST["captcha"]; //WE VALIDATE IF THE INPUTS ARE CORRECTLY INPUT $input = strlen($email)*strlen($password); if ( $_POST["captcha"] ) : $response = $reCaptcha->verifyResponse( $_SERVER["REMOTE_ADDR"], $captcha ); endif; //We validate if exists a response success from google recaptcha and if is it, we continue if ( $response != null && $response->success ) : //if the inputs were in if ( $input > 0 ) : echo 'OWW YEAH, YOU VALIDATE CORRECTLY GOOGLE RECAPTCHA AND YOUR EMAIL IS '.$email.' AND YOUR PASSWORD IS: '.$password; else : echo 'Sorry but you are not fill all the inputs. All are required, please refresh the page and try it again'; endif; else : echo 'Hey, man! Chillout, first validate the google recpatcha and fill the inputs and click the button for continue. Thanks'; endif; endif; /*END OF PHP FILE*/ //BEGIN OUR FORM IN HTML ?> 功能

答案 1 :(得分:3)

你可以Writer w a提升到MonadWriter个实例,例如:

import Control.Monad.Writer (MonadWriter, Writer, runWriter, tell)

lift' :: MonadWriter w m => Writer w a -> m a
lift' wr = do
    let (a, w) = runWriter wr
    tell w    -- manually re-log the log msg
    return a  -- wrap value into new context

然后,你可以写一下:

gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
gameRoutine = do
    a <- lift' writerFunction

只要writerFunction :: Writer [String] a可以专门用a ~ NUM