gpt4 book ai didi

haskell - 使用免费的 monad 和 GADT 进行 pretty-print

转载 作者:行者123 更新时间:2023-12-02 08:28:46 25 4
gpt4 key购买 nike

考虑由以下 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

ExprF 中的 (a -> r) 字段和(否则需要)限制性 GADT 构造函数的组合似乎使得编写 pretty-print 解释器变得不可能:

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 的另一种构造可能会捕获相同的结构,但也支持 pretty-print ?

最佳答案

只是在 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)

关于haskell - 使用免费的 monad 和 GADT 进行 pretty-print ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29455850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com