我在Haskell的一些代码下面发帖.请将代码作为一个例子,我将使用它来解释我想知道的内容.
try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try (a:as) (b:bs) (c:cs) | ((checkIfCorrect a b c) == True) = a:b:[c]
| otherwise = try as bs cs
checkIfCorrect :: [Char] -> [Char] -> [Char] -> Bool
checkIfCorrect a b c = True
Run Code Online (Sandbox Code Playgroud)
最终,只checkIfCorrect返回True一个参数组合.checkIfCorrect功能很长,所以我决定在这里发帖.在上面的示例中,函数checkIfCorrect(通过函数try)应用于:首先[Char]在第一个列表上,第一个[Char]在第二个列表上,第[Char]一个在第三个列表中.如果未满足第一个保护方程,则将函数checkIfCorrect应用于:第[Char]一个列表中的第二个......依此类推.我想达到的目的是将函数checkIfCorrect(通过函数try)应用于[Char]所有列表([[Char]])的所有s 组合.我的意思是以下(例如):第[Char]一个列表上的第三[Char]个,第二个列表上的第八 个,[Char]第三个列表上的第11 个,依此类推.每个人都有.我怎么能轻易达到这个目标?
Ben*_*son 11
我只是想向您展示编写@ WillemVanOnsem代码的另一种方法.我猜你是Haskell的初学者,所以希望这个答案会让你对一个丰富而美丽的想法有一点了解,你很快就会在学习语言的过程中学到很多东西.所以,如果你不理解这段代码的所有内容,请不要太担心; 我只想尝试给你一个味道!
列表理解总是可以使用list monad重新表达:
import Control.Monad (guard)
try as bs cs = head $ do
a <- as
b <- bs
c <- cs
guard $ checkIfCorrect a b c
return [a,b,c]
Run Code Online (Sandbox Code Playgroud)
我使用do符号作为嵌套循环的特殊符号:对于每个ain as,bin in bs和each cin cs,我们产生[a,b,c]if checkIfCorrect返回True.列表推导的翻译很简单:列表推导的"枚举"部分变成"绑定"使用<-,"过滤"变成调用guard,"屈服"变成returns.
在像Python这样的命令式语言中,您可以像这样编写它:
def try(as, bs, cs):
for a in as:
for b in bs:
for c in cs:
if checkIfCorrect(a, b, c):
yield [a,b,c]
Run Code Online (Sandbox Code Playgroud)
就像西方新自由主义霸权下的政治一样,势在必行的代码逐渐向前发展.像这样的"楼梯"代码实际上在命令式编程中频繁出现(想想JS中的"回调地狱"),因此发明monad来帮助抵消这种趋势.事实证明它们非常有用,为它们发明了一种特殊的语法,即 - do注释.
是的,你可以通过列表理解使它看起来更优雅:
try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try as bs cs = head [ [a,b,c] | a <- as, b <- bs, c <- cs, checkIfCorrect a b c ]
-- \__ __/ \__________ ____________/ \__________ _______/
-- v v v
-- yield enumeration filter
Run Code Online (Sandbox Code Playgroud)
代码的工作原理如下:列表推导的右侧部分由" 枚举 "部分组成(由注释部分表示).因为我们写a <- as, b <- bs, c <- cs它意味着a将取任何值as,并且对于每个这样的值a,b将取任何值bs,等等.这意味着将发出每个可能的组合.
接下来是" 过滤器 "阶段:有一个谓词checkIfCorrect a b c将被调用,只有当该谓词返回时True,结果才会被"屈服".
在左侧,我们看到" 收益率 ".它描述了在过滤器成功的情况下要添加到列表中的内容(基于枚举).如果发生这种情况,我们会添加[a,b,c]到该列表 如果有多个此类配置成功,我们最终可能会得到一个包含多个解决方案的列表.但请注意,列表理解是懒惰的:所以只要你不要求至少一个这样的元素,它就不会生成第一个元素,也不会生成第二个元素,等等.
现在我们也需要head(在列表理解之前).head :: [a] -> a返回列表的第一个元素.因此try将返回满足条件的第一个元素.
| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |