我试图在haskell实现vulkan教程的一些部分。
目前,我一直试图从c中翻译这段代码:
for (const char* layerName : validationLayers) {
bool layerFound = false;
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
到目前为止,我已经到了这个地步:
-- This has type (Int -> Text) -> Bool
let partOne = all (`elem` requiredValidationLayers) . flip map [0 .. realCount-1]
-- This has type Int -> IO Text
let partTwo i = do
let layerProperty = advancePtr layerProperties i
myField_ <- readStringField @"layerName" layerProperty
pure $ toS myField_ :: IO Text
我觉得这里有我所有的部分,但我也可能走向一个完全错误的方向。
我怎么把这些东西放在一起?
谢谢
PS:好的,我只是注意到集合包含检查很可能是相反的--没关系,为了这个问题,让我们假装它真的很好
发布于 2020-01-19 15:27:53
谢谢所有的评论,我想我现在明白了:)
如下所示(在do
块的IO ()
中):
supportedLayers <- for [0 .. realCount-1] $ \i -> do
let layerProperty = advancePtr layerProperties i
myField_ <- readStringField @"layerName" layerProperty
pure $ toS myField_ :: IO Text
return $ requiredValidationLayers `includes` supportedLayers
哪里
includes :: Eq a => [a] -> [a] -> Bool
includes a b = all (`elem` b) a
发布于 2020-01-19 15:33:35
我要从一些假设开始:
有一个类型data Layer = ...
type Name = String
layerName :: Layer -> Name
我将介绍纯函数的定义,这并不是因为它非常重要,而是因为它使用了一种从纯函数转换为纯函数(即IO
-dependent)代码的技术。
给定的层是否有给定的名称?
首先,您有基本操作。
strcmp(layerName, layerProperties.layerName) == 0
这是一个简单的Haskell函数,它接受一个Name
和一个Layer
,如果该层具有给定的名称,则返回True
。
hasName :: Name -> Layer -> Bool
hasName name layer = name == layerName layer
几个层中的一个有几个名称中的一个吗?
但是我们没有一个名称或层,我们有每一个的列表。通过使用列表的Applicative
实例来建模不确定性,我们可以轻松地处理这一问题。
import Control.Applicative
foo :: [Name] -> [Layer] -> [Bool]
foo = liftA2 hasName
我不会给这个函数取一个好名字,因为我们不需要一个。
现在,我们可以得到将每个名称与每个层进行比较的结果列表,但我们并不关心单个结果:我们只想要一个值,表示我们是否找到了匹配项。为此,我们将使用or :: [Bool] -> Bool
。
findMatch :: [Name] -> [Layer] -> Bool
findMatch names layers = or (foo names layers)
foo
非常简单,我们只需要内联它的定义,这样我们就不需要想出一个更好的名称了:
findMatch :: [Name] -> [Layer] -> Bool
findMatch names layers = or (liftA2 hasName names layers)
处理IO
现在,我们假设我们已经有了作为纯值的名称和层的列表。但如果我们没有呢?如果只有从文件或其他地方读取的列表,以便有IO [Name]
和/或IO [Layer]
,怎么办?解决方案是再次使用liftA2
,但我们将使用IO
实例,而不是使用Applicative
的list实例。
ionames :: IO [Name]
ionames = ...
iolayers :: IO [Layer]
iolayers = ...
result :: IO Bool
result = liftA2 findMatch ionames iolayers
https://stackoverflow.com/questions/59810018
复制相似问题