【发布时间】:2021-10-17 12:06:36
【问题描述】:
我正在尝试为我正在研究的一种语言编写一个评估函数,在该语言中,可以在 if 块中允许不确定性,称为选择块。我想要实现的是能够从保护为真的块中选择一个 if/selection 语句并对其进行评估,但我选择哪个并不重要。
通过搜索,我找到了一个example,它的执行方式与我希望通过建模硬币翻转实现的方式相似。以下是我对它的改编,但我在将这个逻辑应用于我的问题时遇到了问题。
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 语句的选择块,生成其中的一个子集,其保护为真,并且只从中获取一个语句。
【问题讨论】:
-
在你的函数中加入一些类型。这将帮助 GHC 为您提供更好的错误消息,并帮助该问题的读者(可能还有您!)理解您的意图。
-
@amalloy 我在那里进行了编辑!谢谢!
标签: haskell monads non-deterministic