基本例程实现的'纯'函数式编程有多好,例如列表排序,字符串匹配等?
在任何函数式语言的基本解释器中实现这些基本函数是很常见的,这意味着它们将用命令式语言(c / c ++)编写。虽然有很多例外..
至少,我想问一下:用“纯粹的”功能语言编写时,模仿命令式的风格有多难?
答案 0 :(得分:7)
1)以什么标准好?你想要什么属性?
列表排序?简单。让我们在Haskell做Quicksort:
sort [] = []
sort (x:xs) = sort (filter (< x) xs) ++ [x] ++ sort (filter (>= x) xs)
此代码具有易于理解的优点。如果列表为空,则对其进行排序。否则,调用第一个元素x,找到小于x的元素并对它们进行排序,找到大于x的元素并对它们进行排序。然后将排序列表与中间的x连接起来。尝试在C ++中使其看起来易于理解。
当然,Mergesort对链表的排序速度要快得多,但代码也要长6倍。
2)在保持纯粹功能的同时实现命令式风格非常容易。命令式风格的本质是行动的顺序。使用monad在纯设置中对操作进行排序。 monads的本质是绑定功能:
(Monad m) => (>>=) :: m a -> (a -> m b) -> m b
这个函数存在于C ++中,它被称为;
。
例如,Haskell中的一系列动作就是这样写的:
putStrLn "What's your name?" >>=
const (getLine >>= \name -> putStrLn ("Hello, " ++ name))
可以使用一些语法糖来使这看起来更有必要(但请注意,这是完全相同的代码):
do {
putStrLn "What's your name?";
name <- getLine;
putStrLn ("Hello, " ++ name);
}
答案 1 :(得分:7)
'纯'功能有多好 为基本例程编程 实现,例如列表排序, 字符串匹配等?
非常。我会在Haskell中解决你的问题,对此我会略显冗长。我的目的不是说服你,问题可以用5个字符完成(它可能在J!中),而是让你了解这些结构。
import Data.List -- for `sort`
stdlistsorter :: (Ord a) => [a] -> [a]
stdlistsorter list = sort list
使用sort
Data.List
功能对列表进行排序
import Data.List -- for `delete`
selectionsort :: (Ord a) => [a] -> [a]
selectionsort [] = []
selectionsort list = minimum list : (selectionsort . delete (minimum list) $ list)
选择排序实施。
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
快速排序实施。
import Data.List -- for `isInfixOf`
stdstringmatch :: (Eq a) => [a] -> [a] -> Bool
stdstringmatch list1 list2 = list1 `isInfixOf` list2
使用isInfixOf
Data.list
函数进行字符串匹配
实施这样的基础是很常见的 基本解释器中的函数 任何功能语言,其中 意味着他们将被写成 命令式语言(c / c ++)。虽然 有很多例外..
取决于。有些功能更加自然地表达出来。但是,我希望我已经说服你,某些算法也会以功能的方式自然地表达出来。
至少,我想问:有多难 是模仿命令式的风格 而在'纯'功能编码 语言
这取决于你在Haskell中找到Monads的难度。就个人而言,我觉得很难掌握。
答案 2 :(得分:1)
几乎所有函数式编程语言都有一些构造来允许命令式编码(如Haskell中的do)。有许多问题域无法用“纯”函数编程解决。其中之一是网络协议,例如,您需要以正确的顺序一系列命令。而这些事情并不适合纯函数式编程。
我必须同意Lothar,但是列表排序和字符串匹配并不是您需要强制解决的示例。这些事情有众所周知的算法,它们已经可以在函数式语言中有效地实现。
答案 3 :(得分:1)
我认为'算法'(例如方法体和基本数据结构)是函数式编程最好的地方。假设没有任何完全依赖于IO /状态的函数编程优于编写算法和数据结构,通常会产生比使用命令式解决方案更短/更简单/更清晰的代码。 (不要模仿命令式风格,对于大多数这类任务,FP风格更好。)
您希望有时需要处理IO或低级别性能的命令性内容,并且您希望OOP用于对大型程序的高级设计和体系结构进行分区,但是在“小型”中您编写大部分代码, FP是一场胜利。
另见
How does functional programming affect the structure of your code?
答案 4 :(得分:0)
它的效果非常好,反过来模仿功能性的命令式风格。
请记住,解释器或VM软件的内部非常接近金属和性能至关重要,您甚至应该考虑设置级别并计算每条指令的时钟周期(就像Smalltalk Dophin正在做的那样,结果是令人印象深刻)。 CPU是必不可少的。
但是所有基本算法实现都没有问题 - 你提到的那个是 NOT 低级别 - 它们是基础知识。
答案 5 :(得分:0)
我不知道列表排序,但是你很难在编译器或运行时没有某种字符串匹配的情况下引导一种语言。所以你需要那个例程来创建语言。由于编写相同的代码两次没有太大的意义,当您在语言中创建匹配字符串的库时,您可以调用之前编写的代码。在连续版本中发生这种情况的程度将取决于自我托管语言的方式,但除非这是一个强大的设计目标,否则没有任何理由可以改变它。