交换内部和外部单子

时间:2017-01-22 21:48:36

标签: haskell monads monad-transformers

如何将StateT g (Either E) T转换为ExceptT E (StateT g Identity) T

可能有些traversehoist的混合在这里很有用。

1 个答案:

答案 0 :(得分:9)

You can't exchange an arbitrary pair of monads。但你可以交换这两个特殊的monad。如果你在那些monad变换器的定义中扩展newtype,最容易理解。

鉴于

newtype StateT s m a = StateT { runStateT :: s -> m (s, a) }

newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) }

扩展第一个类型表达式中的newtype会给我们提供同构

StateT s (Either e) a   <->   s -> Either e (s, a)

而第二次我们得到

ExceptT e (StateT s Identity) a   <->   s -> (s, Either e a)

请注意Either e (s, a)可能包含也可能不包含s,而(s, Either e a)总是包含traverse。现在,只需stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either e a)) stateTEitherToExceptTState f s = case f s of Left e -> (s, Left e) Right sa -> fmap Right sa 函数内部的元组就可以从后者转到前者,但是另一种方式需要一些特定于域的推理:如果计算抛出错误,那么我们应该通过对错误的捕手没有改变。 (这是正确的做法吗?我觉得它很有争议。)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.ParseException;
import javax.swing.border.Border;

//@SuppressWarnings("serial")
public class Project1 extends JFrame implements ActionListener { 
public static JButton nextTransformBtn;
public static JButton closeBtn;
//public static JLabel label;
public static JFrame window;
public static JPanel topPanel;
public static DrawArea panel;
public static Border blackLine;
private int frameNumber;  // A counter that increases by one in each frame.
private long elapsedTimeMillis;  // The time, in milliseconds, since the animation started.
private float pixelSize;  // This is the measure of a pixel in the coordinate system
                          // set up by calling the applyWindowToViewportTransformation method.  It can be used
                          // for setting line widths, for example.
public static final int CANVAS_WIDTH = 800;
public static final int CANVAS_HEIGHT = 600;
public static int count ;
int num ;
//public static final String TITLE = " Project 1";


/** constructor
 * @param args 
 */
public Project1() throws ParseException { 
    /**
     * Set properties of Project1 JFrame
     */
    super("Project 1");
    setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
    setLocationRelativeTo(null);
    setResizable(false);
    setBackground( Color.lightGray );
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    /**
     * Creates black line for border
     */        
    blackLine = BorderFactory.createLineBorder(Color.BLACK);

    /**
     * Create a JPanel to display Graphics
     */  
    panel = new DrawArea();
    panel.setBackground(Color.white);
    panel.setBorder(blackLine);

    /**
     * Create components for topPanel
     */     
    //label = new JLabel("    Project 1 ");
    nextTransformBtn = new JButton("Next transform");
    closeBtn= new JButton("Exit Program");

    /**
     * Create a topPanel for text box and
     * set its properties
     */     
    topPanel = new JPanel();
    FlowLayout layout = new FlowLayout();
    topPanel.setLayout(layout);
    topPanel.setBorder(blackLine);
    //topPanel.add(label);
    topPanel.add(nextTransformBtn);
    topPanel.add(closeBtn);

    /**
     * Add topPanel and panel to JFrame
     */ 
    add(topPanel, BorderLayout.NORTH);
    getContentPane().add(panel);

    /**
     * Create ActionListeners for buttons
     */         
    closeBtn.addActionListener(e-> System.exit(0));
    nextTransformBtn.addActionListener(e-> {
        System.out.print (count + " - ");
        panel.doTransform(count);
        panel.redrawComponent();
        count++;
        if(count == 6) count = 0;
    });

}// end constructor method

@Override
public void actionPerformed(ActionEvent e) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}