- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何使用 SYB(或其他一些 Haskell 泛型包)在 Reader
中编写转换使用 local
的 monad修改子计算的环境? GenericM
的类型和 everywhereM
(使用 a -> m a
)似乎不支持使用 local
(类型为 m a -> m a
)包装子计算。如果可能的话,我想要一个使用“标准”/“现成”转换的解决方案。
一个有代表性的例子
一种(神秘的)递归数据类型:
{-# LANGUAGE DeriveDataTypeable , Rank2Types , ViewPatterns #-}
import Data.Generics
import Control.Applicative
import Control.Monad.Reader
import Control.Arrow
data Exp = Var Int | Exp :@ Exp | Lam (Binder Exp)
deriving (Eq , Show , Data , Typeable)
newtype Binder a = Binder a
deriving (Eq , Show , Data , Typeable)
Int
带有值的 s
Binder
的数量s 包装它们:
-- Increment all free variables:
-- If G |- e:B then G,A |- weaken e:B.
weaken1 :: Exp -> Exp
weaken1 = w 0
where
w :: Int -> Exp -> Exp
-- Base case: use the environment ('i'):
w i (Var j) = wVar i j
-- Boilerplate recursive case:
w i (e1 :@ e2) = w i e1 :@ w i e2
-- Interesting recursive case: modify the environment:
w i (Lam (Binder e)) = Lam (Binder (w (succ i) e))
wVar :: Int -> Int -> Exp
wVar i j | i <= j = Var (succ j)
| otherwise = Var j
i
weaken1
的参数在
Reader
环境并使用 SYB 自动处理
(:@)
的样板递归案例.
weaken1
, 使用
Reader
环境,但不是 SYB:
weaken2 :: Exp -> Exp
weaken2 e = runReader (w e) 0
where
w :: Exp -> Reader Int Exp
w (Var j) = do
i <- ask
return $ wVar i j
w (e1 :@ e2) = (:@) <$> w e1 <*> w e2
w (Lam (Binder e)) = Lam . Binder <$> local succ (w e)
(:@)
case 是典型的样板递归:everywhereM
自动在这里工作。 Var
case 使用环境,但不修改它:everywhereM
在这里工作,通过申请 mkM
到 Exp -> Reader Int Exp
特定于 Var
案子。 Lam
case 在递归之前修改环境:everywhereM
在这里不起作用(据我所知)。 Binder
type 告诉我们需要在哪里使用 local
, 以便我们希望申请 mkM
到 Binder Exp -> Reader Int (Binder Exp)
具体情况,但我不知道如何。 最佳答案
这是通过创建新的 SYB 遍历 everywhereMM
的解决方案:
newtype MM m x = MM { unMM :: m x -> m x }
mkMM :: (Typeable a , Typeable b) => (m a -> m a) -> m b -> m b
mkMM t = maybe id unMM (gcast (MM t))
-- Apply a 'GenericM' everywhere, transforming the results with a
-- 'GenericMM'.
type GenericMM m = Data a => m a -> m a
everywhereMM :: Monad m => GenericMM m -> GenericM m -> GenericM m
everywhereMM mm m x = mm (m =<< gmapM (everywhereMM mm m) x)
everywhereMM
的定义和
mkMM
是相似的
everywhereM
和
mkM
在
Data.Generics.Schemes
和
Data.Generics.Aliases
;区别在于
everywhereMM
使用
mm
, 一个
GenericMM
, 转换结果。
weaken3
.这个想法是结合标准
GenericM
对于
Var
的情况
Exp
带有新的
GenericMM
适用
local
在
Binder
案子:
type W = Reader Int
weaken3 :: Exp -> Exp
weaken3 e = runReader (w e) 0
where
w :: GenericM W
w = everywhereMM (mkMM b) (mkM v)
b :: W (Binder Exp) -> W (Binder Exp)
b = local succ
v :: Exp -> W Exp
v (Var j) = do
i <- ask
return $ wVar i j
v e = return e
关于generics - 如何在 Scrap Your Boilerplate (SYB) 中使用 `local` 和 `Reader` monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16806162/
我想写一个rename替换功能String我的 AST 中的名称(代表分层标识符)与 GUID Renamer 中作为隐藏状态携带的符号表中的名称(整数)单子(monad)。 我有一个 AST a在名
在 http://web.archive.org/web/20080622204226/http://www.cs.vu.nl/boilerplate/ 中给出的示例中 -- Increase sal
与 GHC Generics 相比,是否有任何任务只能通过 SYB 才能完成,或者更容易完成? 最佳答案 GHC 泛型是一种相当冗长的方法,用于执行基本上任何查询或遍历。例如,考虑一种具有 Stmt
在 Scrap Your Boilerplate package , 在 Data.Generics.Aliases ,有些函数允许对一元和二元类型构造函数进行类型扩展。特别是对 ext1 有定义和
使用 SYB 对树仅应用一次转换(而不是各处)的最佳方法是什么?例如,在下面的简化表达式中,有多个 Var "x" 实例,我只想用 Var "y" 替换第一个实例。 数据 Exp = 变量字符串 |瓦
我在 Haskell 中发现了一个有趣的库,名为 Scrap Your Boilerplate基于paper by Simon Peyton Jones这似乎是一种有效的方法,可以用函数式编程语言编写
我可以用SYB的gfoldl一次性对listify的结果进行映射吗? 例如考虑以下代码: extractNums :: Expr -> [Int] extractNums e = map numVal
我有一个与 Show 相同的类(class)我想为每个元组类型创建一个此类的实例。通常这是通过为每个元组类型单独编写实例来完成的 instance (Show a, Show b) => Show
如何使用 SYB(或其他一些 Haskell 泛型包)在 Reader 中编写转换使用 local 的 monad修改子计算的环境? GenericM 的类型和 everywhereM (使用 a -
我想使用 SYB在 Shapeless library 中实现编写以下通用遍历函数: class Data // Perform the desired manipulation on the giv
我是一名优秀的程序员,十分优秀!