2

考虑由以下 GADT 定义的表达式函子:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}

import Control.Monad.Free

data ExprF :: * -> * where
  Term :: Foo a -> (a -> r) -> ExprF r

instance Functor ExprF where
  fmap f (Term d k) = Term d (f . k)

type Expr = Free ExprF

其中Foo定义为

data Foo :: * -> * where
  Bar :: Int    -> Foo Int
  Baz :: Double -> Foo Double

instance Show a => Show (Foo a) where
  show (Bar j) = show j
  show (Baz j) = show j

(a -> r)字段 in和(否则理想的)限制性 GADT 构造函数的组合ExprF似乎使编写漂亮的打印解释器变得不可能:

pretty (Pure r)          = show r
pretty (Free (Term f k)) = "Term " ++ show f ++ pretty (k _)

类型孔是人们所期望的:

Found hole ‘_’ with type: a1
Where: ‘a1’ is a rigid type variable bound by
            a pattern with constructor
              Term :: forall r a. Foo a -> (a -> r) -> ExprF r,
            in an equation for ‘pretty’
            at Test.hs:23:15
Relevant bindings include
  k :: a1 -> Free ExprF a (bound at Test.hs:23:22)
  f :: Foo a1 (bound at Test.hs:23:20)
  pretty :: Free ExprF a -> String (bound at Test.hs:22:1)
In the first argument of ‘k’, namely ‘_’
In the first argument of ‘pretty’, namely ‘(k _)’
In the second argument of ‘(++)’, namely ‘pretty (k _)’

似乎没有办法给延续一个它需要的类型的值。该类型被编码为f,而我正在使用的其他解释器都f以某种方式处理以提取适当类型的值。但通往String代表的道路似乎受阻。

我在这里缺少一些常见的成语吗?Expr如果确实有可能,如何漂亮地打印 的值?如果不可能,什么替代结构ExprF可以捕获相同的结构,但还支持漂亮的打印机?

4

2 回答 2

4

只需在f. 如果你这样做,类型k会被细化以匹配里面包含的类型Foo

pretty (Pure r)          = show r
pretty (Free (Term f k)) = "Term " ++ show f ++ pretty r where
  r = case f of
    Bar a -> k a
    Baz a -> k a

您可能想要排除这种模式:

applyToFoo :: (a -> r) -> Foo a -> r
applyToFoo f (Bar a) = f a
applyToFoo f (Baz a) = f a

pretty (Pure r)          = show r
pretty (Free (Term f k)) = "Term " ++ show f ++ pretty (applyToFoo k f)
于 2015-04-05T09:40:08.410 回答
2

好吧,这并非不可能。至少您可以在以下位置进行模式匹配f

pretty :: (Show a) => Expr a -> String
pretty (Pure r) = show r
pretty (Free (Term f@(Bar x) k)) = "Term " ++ show f ++ pretty (k x)
pretty (Free (Term f@(Baz x) k)) = "Term " ++ show f ++ pretty (k x)

但这并不是很令人满意,因为您已经在Foo'sshow实例中这样做了。

因此,挑战是适当地抽象。

于 2015-04-05T09:40:23.187 回答