Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 我怎样才能让这个咖喱实验按预期进行?_Haskell_Currying - Fatal编程技术网

Haskell 我怎样才能让这个咖喱实验按预期进行?

Haskell 我怎样才能让这个咖喱实验按预期进行?,haskell,currying,Haskell,Currying,我正在写一个currying实验,以了解haskell中的多个语句是如何链接在一起,一个接一个地工作的 这是我到目前为止得到的 testCurry :: IO () testCurry = (\b -> (\_ -> putStrLn b) ((\a -> putStrLn a ) (show 2)) ) (show 3) testCurryExpected :: IO ()

我正在写一个currying实验,以了解haskell中的多个语句是如何链接在一起,一个接一个地工作的

这是我到目前为止得到的

testCurry :: IO ()
testCurry =     
    (\b ->
        (\_ -> putStrLn b)
        ((\a -> 
            putStrLn a
        ) (show 2))
    ) (show 3)

testCurryExpected :: IO ()
testCurryExpected = do {
    a <- return (show 2);
    putStrLn a;
    b <- return (show 3);
    putStrLn b;
}

main :: IO ()
main = 
    putStrLn "expected: " >>
    testCurryExpected >>
    putStrLn "given: " >>
    testCurry
注意:出于概念上的考虑,我限制自己使用最多一个参数的匿名函数

编辑:我找到了一个足够好的解决方案,创建了我自己的自由表示的putStrLn,称为Free_putStrLn,不需要解释;使用列表构建操作链,然后自己对其进行评估

data Free_PutStrLn = Free_PutStrLn String deriving Show

eval :: [Free_PutStrLn] -> IO ()
eval a = 
    foldl (\a -> \b -> 
        let deconstruct (Free_PutStrLn str) = str in
        a >> putStrLn (deconstruct b)
    ) (return ()) a

testCurry :: [Free_PutStrLn]
testCurry = 
    (\a ->
        [Free_PutStrLn a] ++
        ((\b ->
            [Free_PutStrLn b]
        ) (show 3))
    )(show 2)

main = 
    putStrLn (show testCurry) >>
    eval (testCurry)
JavaScript概念验证:

// | suspends an object within a function context.
// | first argument is the object to suspend.
// | second argument is the function object into which to feed the suspended
// |     argument(first).
// | third argument is where to feed the result of the first argument feeded into 
// |     second argument. use a => a as identity.
const pure = obj => fn => f => f(fn(obj));

// | the experiment
pure({'console': {
    'log': str => new function log() {
        this.str = str;
    }
}})(free =>
    pure(str => () => console.log(str))
    (putStrLn => 
        pure("hello")(a => 
            [free.console.log(a)].concat (
            pure("world")(b => 
                [free.console.log(b)]
            )(a => a))
        )((result => 
            pure(logObj => logObj.str)
            (deconstruct => 
                result.map(str => putStrLn(deconstruct(str)))
            )(result =>
                result.forEach(f => f())
            )        
        )
    )
    )(a => a)
)(a => a)
但我不知道如何仅使用函数模拟
>
(then)行为

嗯,你不能<代码>>>是(在本例中)关于排序副作用的。Haskell函数永远不会有副作用†。副作用只能发生在一元行为中,因此可以由一元组合子排序,包括但不受
Monad
约束的“做这个也做那个”的概念在Haskell中根本没有任何意义。Haskell函数不是执行的,它只是一个数学变换,您可以对其结果进行评估。该结果本身可能是具有类型的实际操作,例如,
IO()
,这样的操作可以执行和/或与其他操作一元链接。但这实际上与产生这种作用的函数的评估有点正交

这就是答案:“我怎样才能让这个咖喱实验表现得像预期的那样?”你不能,你需要使用一个一元组合词来代替(或者
do
notation,这只是语法上的糖分)


从另一个角度来解决这个问题:你不需要“单子”来表达副作用的顺序。例如,我可以通过生成Python代码来定义“指定副作用”的类型,该代码在执行时具有以下效果:

newtype Effect = Effect { pythons :: [String] }
在这里,您可以通过简单地连接指令列表对效果进行排序。尽管如此,这种排序不是通过任何形式的套用来完成的,而是通过枯燥的列表连接来完成的。最好的接口是:

然后你可以简单地做:

hello :: Effect
hello = Effect ["print('hello')"] <> Effect ["print('world')"]
hello::Effect
你好=效果[“打印('hello')”]效果[“打印('world')”]
只是
mappend
的简写同义词。您也可以定义一个自定义操作符,比如说
#
来链接这些操作,但如果有一个标准类支持某些操作,则通常最好使用它!)

好的,非常精细的排序,不需要一元运算符

但很明显,仅仅计算
hello
不会导致打印任何内容:它只会给您一些其他源代码。实际上,您需要将这些指令提供给Python解释器来完成副作用。
原则上,这与
IO
类型没有区别:评估
IO
操作也不会产生任何副作用,只有将其链接到main(或GHCi repl)才会产生副作用。子表达式中包含多少lambda与此完全无关,因为副作用的发生与函数是否在任何地方被调用无关!它只涉及如何将操作链接到实际的“执行器”,即Python解释器或Haskell自己的
main

如果你现在想知道,如果更简单的
幺半群也能做到这一点,为什么一定是那些古怪的单子呢。。。
Effect
的问题在于它没有返回值。您完全可以通过这种方式生成“纯输出”操作,只需执行预定的Python程序,但您永远无法通过这种方式从Python中获取任何值,以便在Haskell中使用这些值来决定接下来应该发生什么。这是单子允许你做的


†是的,从来没有。Haskell不包括名为。任何人如在评论中提出其他要求,则应予以拒绝

确切地说

但我不知道如何仅使用函数模拟
>
(then)行为

嗯,你不能<代码>>>
是(在本例中)关于排序副作用的。Haskell函数永远不会有副作用†。副作用只能发生在一元行为中,因此可以由一元组合子排序,包括但不受
Monad
约束的“做这个也做那个”的概念在Haskell中根本没有任何意义。Haskell函数不是执行的,它只是一个数学变换,您可以对其结果进行评估。该结果本身可能是具有类型的实际操作,例如,
IO()
,这样的操作可以执行和/或与其他操作一元链接。但这实际上与产生这种作用的函数的评估有点正交

这就是答案:“我怎样才能让这个咖喱实验表现得像预期的那样?”你不能,你需要使用一个一元组合词来代替(或者
do
notation,这只是语法上的糖分)


从另一个角度来解决这个问题:你不需要“单子”来表达副作用的顺序。例如,我可以通过生成Python代码来定义“指定副作用”的类型,该代码在执行时具有以下效果:

newtype Effect = Effect { pythons :: [String] }
在这里,您可以通过简单地连接指令列表对效果进行排序。尽管如此,这种排序不是通过任何形式的套用来完成的,而是通过枯燥的列表连接来完成的。最好的接口是:

然后你可以简单地做:

hello :: Effect
hello = Effect ["print('hello')"] <> Effect ["print('world')"]
hello::Effect
你好=效果[“打印('hello')”]效果[“打印('world')”]
只是
mappend
的简写同义词。您还可以定义一个自定义运算符,比如
#
hello :: Effect
hello = Effect ["print('hello')"] <> Effect ["print('world')"]