gpt4 book ai didi

haskell - Haskell 中的临时命名空间/上下文

转载 作者:行者123 更新时间:2023-12-03 15:10:09 25 4
gpt4 key购买 nike

Io ,您可以使用 do 设置执行上下文:

Http := Object clone
Http get := method(uri, ("<GET request to " .. uri .. ">") println)
Http delete := method(uri, ("<DELETE request to " .. uri .. ">") println)

Database := Object clone
Database insert := method(table, data, ("<insert data to " .. table .. ">") println)
Database delete := method(table, id, ("<delete " .. id .. " from " .. table .. ">") println)

Http do(
get("http://example.com/")
delete("http://example.com/something")
)

Database do(
insert("cats", list("Phil", "gray"))
delete("cats", 12)
)

(Ruby 与 Object#instance_exec 有类似的功能,但它的对象模型有点复杂。)

实际上,这为您提供了一个临时命名空间,非常适合编写特定领域的语言。有没有一种技术可以在 Haskell 中实现类似的效果(临时命名空间)?

例如,类似:(不一定完全像这样,但具有类似简洁语法的东西。)
main = do
http $ do
get "http://example.com/"
delete "http://example.com/something"
database $ do
insert "cats" ["Phil", "gray"]
delete "cats" 12

请注意,这两个 delete s 是完全不同的函数。我宁愿避免写 H.delete 之类的东西和 D.delete ,因为那会很快变得困惑。我意识到可以通过将数据库版本重命名为 deleteFrom 来避免这种情况。 ,但我不想。

最佳答案

“那是疯狂的动态东西。你永远无法用静态语言做到这一点......”

{-# LANGUAGE ImplicitParams, Rank2Types #-}
import Text.Printf
http :: (((?get :: String -> IO ()),
(?delete :: String -> IO ()))
=> IO a)
-> IO a
http a = let ?get = \s -> printf "http get %s\n" s
?delete = \s -> printf "http delete %s\n" s
in a

database :: (((?insert :: String -> [String] -> IO ()),
(?delete :: String -> Integer -> IO ()))
=> IO a)
-> IO a
database a = let ?insert = \s ls -> printf "database insert %s %s\n" s (show ls)
?delete = \s n -> printf "database delete %s %d\n" s n
in a

main = do
http $ do
?get "http://example.com/"
?delete "http://example.com/something"
database $ do
?insert "cats" ["Phil", "gray"]
?delete "cats" 12

“这太疯狂了。这不可能”
*Main> :l Crazy.hs 
[1 of 1] Compiling Main ( Crazy.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
http get http://example.com/
http delete http://example.com/something
database insert cats ["Phil","gray"]
database delete cats 12

您可能实际上不应该以这种方式做事。但如果这真的是你想要的,隐式参数可能是最优雅的获取方式

applicative 的 RecordWildCard 解决方案在某种意义上比这更好,因为它需要更少的代码来设置,并且涉及的语言扩展要小得多。此外,它非常类似于在具有适当模块系统的语言中使用“开放”指令,或在具有灵活名称间距的语言中使用“使用命名空间”命令(Haskell 两者都没有)。隐式参数解决方案捕获类似于动态语言语义的东西。特别是,使用它,您可以调用使用隐式参数的函数,而不必担心手动传递环境。

您还可以在此处使用 ReaderT 或类似的东西模拟隐式参数。虽然(由于各种原因),如果你想留在 Haskell 98 中,那不是很有组合性。

关于haskell - Haskell 中的临时命名空间/上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11661963/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com