如何将StateT g (Either E) T
转换为ExceptT E (StateT g Identity) T
?
可能有些traverse
和hoist
的混合在这里很有用。
答案 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.
}
}