haskell - это -ddump-упрощенный лучший способ получить конкретный тип? - PullRequest
3 голосов
/ 03 ноября 2011

Ранее я написал функцию, которая, кажется, работает, но, к сожалению, я не очень хорошо написал код, и теперь мне нужно снова разобраться в этом [что я модифицирую стек монадного преобразователя, с которым я работаю].

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 и проходить через мой вывод терминала, пока не найду, (немного почистил)

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

(Извините, это, вероятно, глупость для всех остальных, но сутьэто полезно для меня.) Есть ли более быстрый / более удобный способ сделать это?В случае, если это не очевидно, я подразумеваю под «конкретным» в данном случае то, что вышеуказанный тип полезен;Знание типа snd . fst не является:).

Ответы [ 2 ]

8 голосов
/ 03 ноября 2011

В настоящее время я знаю, как сделать это двумя способами, и оба они вроде хаки.Первый - использовать неявные параметры:

{-# 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) -> ().Одна последняя итерация избавляет от финальной (), потому что компилятор жалуется, что:

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

... поэтому другая () должна быть Seq SketchAST.

3 голосов
/ 03 ноября 2011

Обмани компилятору.Добавьте неверную сигнатуру типа, затем она должна ответить «Не удалось сопоставить неправильный тип с реальным типом» или каким бы ни было точное сообщение в данный момент.

...