用函数语言将命令表示为数据的名称?

问题描述 投票:0回答:1

这是一个关于在我看来函数式编程中非常常见的模式的名称的问题。

在像 Haskell 这样的纯函数式编程语言中,程序的“外部”部分通常允许执行 IO 副作用,例如打印到屏幕或写入数据库(例如 IO monad),然后是程序的内部部分仅由纯函数组成的程序。

如果纯函数想要执行某种副作用,例如打印,可以将其表示为代数数据类型的值,该值返回到外部 IO 部分,然后在其中执行。

这是一个有点人为的例子:

data Command = PutStrLn String

fizz :: Int -> Command
fizz n | n `mod` 15 == 0  = PutStrLn "FizzBuzz"
       | n `mod` 3  == 0  = PutStrLn "Fizz"
       | n `mod` 5  == 0  = PutStrLn "Buzz"
       | otherwise        = PutStrLn (show n)
       
runCommand :: Command -> IO ()
runCommand (PutStrLn str) = putStrLn str
       
main :: IO ()
main = mapM_ runCommand $ map fizz [1..100]

fizz
函数是完全纯粹的,但我不只是返回
String
,而是选择了字符串以及预期的效果。这里使用 fizzuzz 只是一个玩具示例,用于展示
Command
类型和有效的
runCommand
函数之间的关系。

在更复杂的程序中,

fizz
将是我的应用程序逻辑的一部分,并且
Command
可以是例如代表 Web API 或操作系统调用或其他一些 IO 效果。

是否有一个名称可以用这种方式表示有效的 API 和数据?

haskell design-patterns functional-programming
1个回答
0
投票

我经常看到纯部分被描述为特定领域语言 (DSL) 的抽象语法树 (AST),而“运行”函数则被描述为该语言的解释器

正如 Fyodor Soikin 在评论中提到的,免费 monad 可以被视为这种编程风格的一个例子。

Gary Bernhardt 称之为“功能核心,命令外壳”。 通常 AST 被定义为递归求和类型,并且由于

求和类型与访问者模式同构

,如果您更倾向于面向对象,您也可以将解释器视为访问者。 (需要明确的是,不是在 Haskell 中,而是在其他上下文中。) 在我看来,这种编程风格独立地出现在多个地方,并且通常有一位作者/发明者不了解现有技术。因此,即使有很多重叠,您也会发现不同的名称。

© www.soinside.com 2019 - 2024. All rights reserved.