3

我之前写过一个似乎可以工作的函数,但不幸的是我没有很好地编写代码,现在不得不再次弄清楚[我正在修改我正在使用的 monad 转换器堆栈]。

run_astvn ::
    LowerMonadT (StateT LowerSketchData Identity) β
    -> Seq SketchAST
run_astvn x = get_ast2 $ runIdentity $
    runStateT (runStateT (runStateT x empty) empty)
        (LowerSketchData Set.empty)
    where get_ast2 = snd . fst

我想获得具体类型的get_ast2. 我似乎能够-ddump-simpl通过我的终端输出添加标志和 grep 直到我找到,(清理一点)

(((β, Seq SketchAST), Seq SketchAST), LowerSketchData) -> Seq SketchAST

(抱歉,这对其他人来说可能是胡说八道,但关键是它对我有用。)有没有更快/更方便的方法来做到这一点?如果不明显,在这种情况下,我所说的“具体”是指上述类型很有用;知道的类型snd . fst不是:)。

4

2 回答 2

8

目前我知道有两种方法可以做到这一点,它们都是黑客。首先是使用隐式参数:

{-# LANGUAGE ImplicitParams #-}
import Control.Monad.State
import Control.Monad.Identity
import Data.Sequence
import qualified Data.Set as Set

data LowerSketchData = LowerSketchData (Set.Set Int)
type LowerMonadT m = StateT (Seq SketchAST) (StateT (Seq SketchAST) m)
data SketchAST = SketchAST

--run_astvn ::
--    LowerMonadT (StateT LowerSketchData Identity) β
--    -> Seq SketchAST
run_astvn x = ?get_ast2 $ runIdentity $
    runStateT (runStateT (runStateT x empty) empty)
        (LowerSketchData Set.empty)
--    where get_ast2 = snd . fst

然后,在 ghci 中:

*Main> :t run_astvn
run_astvn
  :: (?get_ast2::(((a, Seq a1), Seq a2), LowerSketchData) -> t) =>
     StateT
       (Seq a1) (StateT (Seq a2) (StateT LowerSketchData Identity)) a
     -> t

另一种方法是故意给出错误的类型签名并检查编译器如何抱怨。

import Control.Monad.State
import Control.Monad.Identity
import Data.Sequence
import qualified Data.Set as Set

data LowerSketchData = LowerSketchData (Set.Set Int)
type LowerMonadT m = StateT (Seq SketchAST) (StateT (Seq SketchAST) m)
data SketchAST = SketchAST

run_astvn ::
    LowerMonadT (StateT LowerSketchData Identity) β
    -> Seq SketchAST
run_astvn x = get_ast2 $ runIdentity $
    runStateT (runStateT (runStateT x empty) empty)
        (LowerSketchData Set.empty)
--    where get_ast2 = snd . fst
    where get_ast2 :: (); get_ast2 = undefined

这给出了错误:

test.hs:13:19:
    The first argument of ($) takes one argument,
    but its type `()' has none
    In the expression:
      <snip>

将错误的类型更改为() -> ()

test.hs:13:30:
    Couldn't match expected type `()'
                with actual type `(((β, Seq SketchAST), Seq SketchAST),
                                   LowerSketchData)'
    In the second argument of `($)', namely
      <snip>

所以现在我们知道类型应该是这样的(((β, Seq SketchAST), Seq SketchAST), LowerSketchData) -> ()。最后一次迭代摆脱了 final (),因为编译器抱怨:

test.hs:13:19:
    Couldn't match expected type `Seq SketchAST' with actual type `()'
    In the expression:
      <snip>

...所以另一个()应该是Seq SketchAST

于 2011-11-03T01:11:44.380 回答
3

对编译器撒谎。添加错误的类型签名,然后它应该回复“无法将错误类型与真实类型匹配”或当前的确切消息。

于 2011-11-03T00:59:24.713 回答