通过List Monad模拟非确定性选择



我正试图为我正在研究的一种语言编写一个评估函数,其中在if块(称为选择块)中允许非确定性。我想要实现的是从block中选择一个if/selection语句,它的守卫为true,并对其求值,但我选择哪一个并不重要。

从搜索中,我发现了一个示例,其执行方式与我想通过建模硬币硬币实现的方式相似。下面是我对它的改编,但是我在应用这个逻辑到我的问题上有问题。

import Control.Monad
data BranchType = Valid | Invalid deriving (Show)
data Branch = If (Bool, Integer) deriving (Show, Eq)
f Valid   = [If (True, 1)]
f Invalid = [If (False, 0)]
pick = [Invalid, Invalid, Valid, Invalid, Valid]
experiment = do
b <- pick
r <- f b
guard $ fstB r
return r
s = take 1 experiment
fstB :: Branch -> Bool
fstB (If (cond, int)) = cond
main :: IO ()
main = putStrLn $ show $ s -- shows first branch which could be taken.

下面是我的ADT和我一直在努力做的工作:

data HStatement
= Eval    HVal
| Print   HVal
| Skip    String
| Do      HVal [HStatement]
| If      (HVal, [HStatement])
| IfBlock [HStatement] -- made up of many If
| Select  [HStatement] -- made up of many If
deriving (Eq, Read)

fstIf :: HStatement -> Bool
fstIf (If (cond, body)) = if hval2bool cond == True
then True
else False
h :: Env -> HStatement -> IOThrowsError ()
h env sb = do
x <- g env sb
guard $ fstIf x -- Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’
-- after guard, take 1 x then evaluate 

g :: Env -> HStatement -> IOThrowsError [HStatement]
g env (Select sb) = mapM (x -> f env x) sb
f :: Env -> HStatement -> IOThrowsError HStatement
f env (If (cond, body)) = evalHVal env cond >>= x -> case x of
Bool True  -> return $ If (Bool True,  body)
Bool False -> return $ If (Bool False, body)

我收到的错误如下:Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’guard行。我相信第一部分代码之所以成功是因为这些值是从List中提取的,但在第二种情况下,尽管它们是从列表中提取的,但它们是从[HStatement]中提取的,而不仅仅是代表列表的东西……如果这有任何意义的话,我觉得我错过了词汇。

本质上,应该发生的事情是给定一个n语句的选择块,这些语句的一个子集被生成,其保护为真,并且只从其中取出一条语句。

错误消息现在非常清楚,因为您已经写下了一些类型。g返回IOThrowsError [HStatement],因此当您将其结果绑定到h中的x时,您将得到[HStatement]。然后调用fstIf,它需要一个HStatement,而不是一个列表。您需要决定如何处理来自g的多个结果。

最新更新