Haskell:实际的IO monad实现,使用不同的语言? [英] Haskell: actual IO monad implementation, in different language?

查看:125
本文介绍了Haskell:实际的IO monad实现,使用不同的语言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

IO monad实际上是如何实现的?从 main 函数的实际实现是什么?



如何从另一种语言调用haskell函数(IO),并且在这种情况下是否需要维护IO我的自我?

是否 main 将IO操作(Lazily)作为引用,然后调用它们?
或者它是翻译工作,当它发现它可以调用它们的行为时?
或者也许别的东西?



是否有不同语言的IO monad实现可以帮助深入理解main函数中发生的事情?

编辑:



这样的 hGetContents 让我很困惑,并且让我不确定IO是如何实现的。好吧,比方说,我有非常简单的纯Haskell解释器女巫不幸的是没有IO支持和好奇心我想添加这个IO动作到它( unsafeIO 技巧也)。很难从GHC,Hugs或其他人处获得它。

解决方案

这是一个如何实现IO monad在Java中:

  package so.io; 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

导入static so.io.IOMonad。*;
导入static so.io.ConsoleIO。*;

/ **
*这是一个不包含数据的类型 - 对应于Haskell中的()。
* /
class单元{
public final static单元VALUE = new Unit();
}

/ **
*此类型表示从A到R
* /
的函数interface函数< A,R> {
public R apply(A argument);
}

/ **
*这种类型表示一种动作,产生类型R
* /
接口IO< R> {
/ **
*警告!可能会有任意的副作用!
* /
R unsafePerformIO();

$ b / **
*这个内部不纯的类提供了纯粹的行为排序接口(又名Monad)
* /
class IOMonad {
static< T> IO< T>纯粹的(最终的T值){
返回新的IO< T>(){
@Override
public T unsafePerformIO(){
return value;
}
};
}

static< T> IO< T> join(final IO< IO< T> action){
return new IO< T>(){
@Override
public T unsafePerformIO(){
return action。 。unsafePerformIO()unsafePerformIO();
}
};
}

static< A,B> IO< B个fmap(final Function< A,B> func,final IO< A> action){
return new IO< B>(){
@Override
public B unsafePerformIO(){
return func.apply(action.unsafePerformIO());
}
};
}

static< A,B> IO< B个绑定(IO< A> action,Function< A,IO< B> func){
return join(fmap(func,action));


$ b $ ** b $ b *这个类在内部不纯,提供了与stdin和stdout交互的纯界面
* /
类ConsoleIO {
static IO< Unit> putStrLn(final String line){
return new IO< Unit>(){
@Override
public unit unsafePerformIO(){
System.out.println(line);
返回Unit.VALUE;
}
};
};

// Java没有第一类函数,因此:
final static Function< String,IO< Unit>> putStrLn = new Function< String,IO< Unit>>(){
@Override
public IO< Unit> apply(String argument){
return putStrLn(argument);
}
};

final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

static IO< String> getLine = new IO< String>(){
@Override
public String unsafePerformIO(){
try {
return in.readLine();
} catch(IOException e){
throw new RuntimeException(e);
}
}
};
}

/ **
*程序由纯粹功能性的IO操作构成。
* /
class Main {

/ **
*绑定的一种变体,它放弃绑定值。
* /
static IO< Unit> bind_(final IO< Unit> a,final IO< Unit> b){
return bind(a,new Function< Unit,IO< Unit>>(){
@Override
公共IO< Unit> apply(Unit argument){
return b;
}
});
}

/ **
*问候操作 - 询问用户名字,然后打印问候语
* /
final static IO< ;单元> greet =
bind_(putStrLn(Enter your name:),
bind(getLine,new Function< String,IO< Unit>>(){
@Override
public IO< Unit> apply(String argument){
return putStrLn(Hello,+ argument +!);
}
}));
$ b $ **
*简单的echo操作 - 读取一行,将其打印出来
* /
final static IO< Unit> echo = bind(getLine,putStrLn);
$ b $ / **
*执行一些动作并产生相同动作的函数永远反复运行(模栈溢出:D)
* /
静态IO<单元> ;循环(final IO action){
return bind(action,new Function< Unit,IO< Unit>>(){
@Override
public IO< Unit> apply单元参数){
return loop(action);
}
});
}

/ **
*整个程序对应的动作
* /
最终静态IO<单位> main = bind_(greet,bind_(putStrLn(进入回声循环。),循环(回声)));
}

/ **
*运行系统,执行不纯的东西来实际运行我们的程序。
* /
public class RTS {
public static void main(String [] args){
Main.main.unsafePerformIO();




$ b $ p $这是一个运行时系统, / O连同一个小的纯功能程序,它迎合用户,然后运行一个回声循环。

不能在Haskell中实现不安全的部分,因为Haskell是纯粹的功能语言。它总是与较低级别的设施一起实施。


How is IO monad actually implemented?in sense of, what would be the actual implementation of the main function?

How would I call haskell function (IO) from another language and do I in that case need to maintain IO my self?

Does main pulls IO actions (Lazily) as references and then call them? Or it is interpreter job, when it found actions in its way it can call them? Or maybe something else?

Is there good IO monad implementation in different language which can help to deeply understand what happening in main function?

Edit:

Such hGetContents confuses me a lot, and makes me unsure how IO is really implemented.

Ok, let's say I have very simple pure Haskell interpreter witch unfortunately has no IO support and for curiosity I want to add this IO actions to it (unsafeIO tricks also). It is hard to get it from GHC, Hugs or others.

解决方案

Here is an example of how one could implement the IO monad in Java:

package so.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import static so.io.IOMonad.*;  
import static so.io.ConsoleIO.*;    

/**
 * This is a type containing no data -- corresponds to () in Haskell.
 */
class Unit {
    public final static Unit VALUE = new Unit(); 
}

/**
 * This type represents a function from A to R
 */
interface Function<A,R> {
    public R apply(A argument);
}

/**
 * This type represents an action, yielding type R
 */
interface IO<R> {
    /**
     * Warning! May have arbitrary side-effects!
     */
    R unsafePerformIO();
}

/**
 * This class, internally impure, provides pure interface for action sequencing (aka Monad)
 */
class IOMonad {
    static <T> IO<T> pure(final T value) {
        return new IO<T>() {
            @Override
            public T unsafePerformIO() {
                return value;
            }
        };
    }

    static <T> IO<T> join(final IO<IO<T>> action) {
        return new IO<T>(){
            @Override
            public T unsafePerformIO() {
                return action.unsafePerformIO().unsafePerformIO();
            }
        };
    }

    static <A,B> IO<B> fmap(final Function<A,B> func, final IO<A> action) {
        return new IO<B>(){
            @Override
            public B unsafePerformIO() {
                return func.apply(action.unsafePerformIO());
            }
        };
    }

    static <A,B> IO<B> bind(IO<A> action, Function<A, IO<B>> func) {
        return join(fmap(func, action));
    }
}

/**
 * This class, internally impure, provides pure interface for interaction with stdin and stdout
 */
class ConsoleIO {
    static IO<Unit> putStrLn(final String line) {
        return new IO<Unit>() {
            @Override
            public Unit unsafePerformIO() {
                System.out.println(line);
                return Unit.VALUE;
            }
        };
    };

    // Java does not have first-class functions, thus this:
    final static Function<String, IO<Unit>> putStrLn = new Function<String, IO<Unit>>() {
        @Override
        public IO<Unit> apply(String argument) {
            return putStrLn(argument);
        }
    };

    final static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    static IO<String> getLine = new IO<String>() {
            @Override
            public String unsafePerformIO() {
                try {
                    return in.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
}

/**
 * The program composed out of IO actions in a purely functional manner.
 */
class Main {

    /**
     * A variant of bind, which discards the bound value.
     */
    static IO<Unit> bind_(final IO<Unit> a, final IO<Unit> b) {
        return bind(a, new Function<Unit, IO<Unit>>(){
            @Override
            public IO<Unit> apply(Unit argument) {
                return b;
            }
        });
    }

    /**
     * The greeting action -- asks the user for his name and then prints a greeting
     */
    final static IO<Unit> greet = 
            bind_(putStrLn("Enter your name:"), 
            bind(getLine, new Function<String, IO<Unit>>(){
                @Override
                public IO<Unit> apply(String argument) {
                    return putStrLn("Hello, " + argument + "!");
                }
            }));

    /**
     * A simple echo action -- reads a line, prints it back
     */
    final static IO<Unit> echo = bind(getLine, putStrLn);

    /**
     * A function taking some action and producing the same action run repeatedly forever (modulo stack overflow :D)
     */
    static IO<Unit> loop(final IO<Unit> action) {
        return bind(action, new Function<Unit, IO<Unit>>(){
            @Override
            public IO<Unit> apply(Unit argument) {
                return loop(action);
            }
        });
    }

    /**
     * The action corresponding to the whole program
     */
    final static IO<Unit> main = bind_(greet, bind_(putStrLn("Entering the echo loop."),loop(echo)));
}

/**
 * The runtime system, doing impure stuff to actually run our program.
 */
public class RTS {
    public static void main(String[] args) {
        Main.main.unsafePerformIO();
    }
}

This is a runtime system implementing interface to the console I/O together with a small purely functional program which greets the user and then runs an echo loop.

One can't implement the unsafe part in Haskell because Haskell is purely functional language. It is always implemented with lower-level facilities.

这篇关于Haskell:实际的IO monad实现,使用不同的语言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆