haskell - 使用枪夹填充位置参数

标签 haskell

假设我有以下 Haskell 程序:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data

data A = A Int Int
    deriving (Show, Typeable, Data)

main = print (f (toConstr (A undefined undefined)))

f :: Constr -> A
f c = _

我想实现f这样它的类型就是 Constr -> A ,因此它在功能上等同于 A 1 2 。但是,我不想使用实际的构造函数;我只被允许使用Constr对于 A ,和gunfold 。实际上,我如何使用 gunfold应用构造函数,同时为每个构造函数位置提供不同的参数?越简单/越高效越好。

这里有更多背景信息:http://comments.gmane.org/gmane.comp.lang.haskell.libraries/24594 (具体来说,请参阅 Michael Sloan 的评论。)本质上,我们正在生成代码来使用 Template Haskell 调用构造函数;但是,由于我们的基础是 Data例如,在一天结束时,我们必须经历 Data在有人使用虚拟构造函数的情况下获得正确的行为。

最佳答案

fromConstrM源自gunfold。 您可以将它与 State 一起使用,对构造函数的 Int 字段进行简单编号。

import Data.Maybe
import Control.Monad.Trans.State

numbered :: Data d => State Int d
numbered = fromMaybe (fail  "numbered - don't know which constructor to use next") $ gcast $ do
    i <- get
    put (i + 1)
    return i

f :: Constr -> A
f c = fst . runState (fromConstrM numbered c) $ 1

如果您知道构造函数的参数是什么,您可以将它们保存在状态列表中,并在使用时对每个参数进行强制转换。

import Data.Dynamic

fillArgs :: Data d => State [Dynamic] d
fillArgs = do
    args <- get
    case args of 
        [] -> fail "fillArgs - not enough arguments provided"
        (x:xs) -> maybe
            (fail "fillArgs - type mismatch")
            (\x -> do
                put xs
                return x
            )
            (fromDynamic x)

applyConstr :: Data d => Constr -> [Dynamic] -> d
applyConstr c = fst . runState (fromConstrM fillArgs c)

f :: Constr -> A
f c = applyConstr c (map toDyn ([1..] :: [Int]))

关于haskell - 使用枪夹填充位置参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30058605/

相关文章:

haskell - 存在类型作为返回值

haskell - 列出附加元素的 monad 实例

haskell - concatMap f xs 和 concat $ map f xs 的区别?

haskell - 将大型记录类型的解析器提升为仿函数

haskell - 我这里的类型签名有什么问题?

Haskell 解析工具 - yacc:lex::happy:?

haskell - Haskell 的箭头运算符的 'real' 名称是什么?

algorithm - 如何向该示例添加并行计算?

haskell - 对 Haskell FFI 的反馈

在 Haskell 中动态构建列表理解