首页 > 解决方案 > 为什么 traceM 并不总是在 Haskell 中给出输出?

问题描述

我有以下函数,它接受Expr并输出 a [Typing],我只是插入一个 traceM 来查看函数在特定表达式上的行为。但是,它没有按应有的方式打印,我想知道为什么。

表达式如下所示:

data Expr = Vi Int
          | Vb Bool
          | Vv Name
          | App Expr Expr
          | Lam Name Typ1 Expr
          deriving(Generic, Eq)

我正在运行的示例是这个:

(App (App (Lam "x" dyn (Lam "y" dyn (Vv "x"))) (Vv "f")) (App (Vv "f") (Vv "x")))

代码在这里。我不确定所有这些是否相关,但我试图打印进入“应用程序”案例时会发生什么。所以我用 traceM 看看在这种情况下会发生什么。

infer :: Expr -> [Typing]
infer expr = evalState (go expr) 0 where

go = \case
    (Vi _) -> do
      return [([], CInt)]

    Vb _ -> do
      return [([], CBool)]

    (Vv x) -> do
      v <- fresh
      return [([(x, v)], v)]

    (Lam x _ f) -> do
      lst <- go f -- list of all possile typings
      forM lst $ \(gamma, ty_e) -> do
        case lookup x gamma of
          Just typ -> do
            let v = CArr typ ty_e
            return (filter (\a -> x /= fst a) gamma, v)
          Nothing -> do
            v <- fresh 
            return (gamma , (CArr v ty_e))

    (App m1 m2) -> do
      (m1list, m2list) <- liftM2 (,) (go m1) (go m2)
      traceM (show m2 ++  " - " ++ show m2list ++ " \n ")
      traceM (show m1 ++  " - " ++ show m1list)
      traceM (show "app " ++ show (App m1 m2))

      fmap concat . forM m1list $ \(lam_env, t) -> do
        case t of
          CArr t1 t2 -> do
            let (m2env, m2types) = unzip m2list
            u' <- pleaseUnifyList (get_conj_elts t1) m2types
            -- traceM (show "list" ++ show u')
            -- traceM (show "possible empty list" ++ show (lam_env .+. solsum m2env, t2) )
            return $ case u' of 
              Right u -> [ substituteTyping u (lam_env .+. solsum m2env, t2) ]
              Left _ -> []

          _ -> do
            fmap concat . forM m2list $ \(app_env, s2) -> do
              (t1, t2) <- liftM2 (,) fresh fresh
              solve_all [t !> (t1 .~> t2), s2 .< t1, s2 !~ t1] lam_env app_env t2

当我运行此代码时,我得到以下信息:

"app "(λx:*.λy:*.x) f 

λx:*.λy:*.x - [([],0 -> 1 -> 0)]
f - [([("f",2)],2)] 

"app "f x 

f - [([("f",3)],3)]
x - [([("x",4)],4)] 

这段代码应该为每个 App 构造函数打印“app”。此表达式中有三个 App 构造函数,但它只打印两次。特别是,我缺少最外层的构造函数。这怎么可能?

编辑

infer :: Expr -> [Typing]
infer expr = evalState (go expr) 0 where
  go = \case
    (Vi _) -> do
      return []

    Vb _ -> do
      return []

    (Vv x) -> do
      return []

    (Lam x f) -> do
        return []

    (App m1 m2) -> do
      (m1list, m2list) <- liftM2 (,) (go m1) (go m2)
      traceM (show m2 ++  " - " ++ show m2list ++ " \n ")
      traceM (show m1 ++  " - " ++ show m1list)
      traceM (show "app " ++ show (App m1 m2))
      return []

删除大部分代码并运行上面的代码后,根本没有打印出来。在语法上,Lam Name Typ1 Expr应修改为Lam Name Expr.

标签: haskellmonadsmonad-transformers

解决方案


推荐阅读