【问题标题】:Simulating non-deterministic choice through the List Monad通过 List Monad 模拟非确定性选择
【发布时间】: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


【解决方案1】:

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

【讨论】:

  • guard不是问题吗?处理来自g 的多个实例已经是我正在尝试做的事情(我认为)。我正在尝试模拟我从pick中绘制的第一个代码块,将f应用于它,然后使用guard,但在guard的特定实例中,它看起来好像是在应用布尔检查整个数组。
  • 在您的experimentf b :: [Branch] 中,然后当您在List monad 中绑定到它时,您会得到r :: Branch,这是调用fstB 的正确类型。在h 中,您无需执行任何操作来从列表中提取单个元素。
  • 我现在完全理解你了!回到绘图板!
猜你喜欢
  • 2014-01-05
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 2017-11-07
相关资源
最近更新 更多