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

标签 haskell monads non-deterministic

我正在尝试为我正在开发的语言编写一个评估函数,其中可以在 if block (称为选择 block )中允许非确定性。我想要实现的是能够从守卫为 true 的 block 中选择一个 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] 中提取的。 ,而不是仅仅代表一个列表的东西...如果这有任何意义的话,我觉得我错过了词汇表。

本质上,应该发生的事情是给定一个选择 block n语句,生成其中的一个子集,其守卫为 true,并且仅从中获取一个语句。

最佳答案

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

关于haskell - 通过 List Monad 模拟非确定性选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68785880/

相关文章:

Haskell,测量函数的 CPU 时间

list - 为什么 Curry 的标准库中的非确定性选择函数没有直接定义,而是使用辅助 2 参数函数定义?

sql - MSSQL 为什么这个函数是非确定性的

c - C float 是不确定的吗?

haskell - 在haskell中调用函数

haskell - 如何让 ReaderT 与另一个 monad 转换器一起工作?

monads - 为部分应用的函数绑定(bind)类实例

f# - 可以访问计算表达式的参数吗?

Haskell IO Int 和 Int

c - Haskell Z3 api 的段错误