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