【问题标题】:Can some explain the reflection package API in *very* simple terms?有人可以用*非常*简单的术语解释反射包 API 吗?
【发布时间】:2021-02-28 09:55:05
【问题描述】:

我很难理解描述反射包的文档/示例。我是一名命令式编程老手,但也是一名 Haskell 新手。可以简单介绍一下吗?

包裹:https://hackage.haskell.org/package/reflection

编辑:致结束此问题的人:这是对 Haskell 反射的初学者介绍。下面的答案很好,其他的也很有用,所以请重新打开。

【问题讨论】:

标签: haskell reflection proxy reify


【解决方案1】:

在最简单的用例中,如果您有一些配置信息希望在一组函数中普遍可用:

data Config = Config { w :: Int, s :: String }

您可以为需要访问配置的函数添加Given Config 约束:

timesW :: (Given Config) => Int -> Int

然后使用值given 来引用当前配置(因此w givens given 来引用其字段):

timesW x = w given * x

还有一些其他功能,有些使用配置,有些不使用:

copies :: Int -> String -> String
copies n str = concat (replicate n str)

foo :: (Given Config) => Int -> String
foo n = copies (timesW n) (s given)

然后您可以在 give 的不同配置下运行计算:

main = do
  print $ give (Config 5 "x") $ foo 3
  print $ give (Config 2 "no") $ foo 4

这类似于:

  • 全局定义given :: Config,除非你可以在同一个程序的多个配置下运行计算;

  • 将配置作为额外参数传递给每个函数,除非您避免显式接受配置并传递它的麻烦,例如:

    timesW cfg x = w cfg * x
    foo cfg n = copies (timesW cfg n) (s cfg)
    
  • 使用 Reader monad,但您不必将所有内容都提升为笨拙的 monad 或应用程序级语法,例如:

    timesW x = (*) <$> asks w <*> pure x
    foo n = copies <$> timesW n <*> asks s
    

完整示例:

{-# LANGUAGE FlexibleContexts #-}

import Data.Reflection

data Config = Config { w :: Int, s :: String }

timesW :: (Given Config) => Int -> Int
timesW x = w given * x

copies :: Int -> String -> String
copies n str = concat (replicate n str)

foo :: (Given Config) => Int -> String
foo n = copies (timesW n) (s given)

main = do
  print $ give (Config 5 "x") $ foo 3
  print $ give (Config 2 "no") $ foo 4

【讨论】:

  • 这很好,感谢您抽出宝贵时间。这真的感觉像是另一种处理隐式参数的方式,对吗?为什么要准确地称之为“反射”?它不符合我之前对那个词的直觉。
  • 如果您查看原始文章 (Kiselyov and Shan, "Functional Pearl: Implicit Configurations"),他们会将其与 6.2 节中的隐式参数进行比较。术语“反射”指的是实现方法:运行时配置值从值级别“反射”到类型级别。通常在编程中,“反射”指的是相反方向的反射,从类型级别到值级别(例如,Java 中的反射),但它是相同的想法。
  • 实际上,从技术上讲,reflection 包提供的reflect 函数接受类型级别的参数并返回其值级别的值,而reify 用于获取值级别的值到类型级别,所以这里“反射”的预期含义实际上可能是通常的类型级别到值级别的方向。
  • 嗯,我不确定原始文章第 6.2 节中的比较是否适用于 reflection 包。特别是,文章使用了ST-style 幻像参数来允许多个相同类型的Givens,而不用担心在错误的时间用错了。几个比较点源于此消歧功​​能 - 可能全部,我不清楚。
  • 这不是真正应该如何使用GivengiveGiven 最好被视为一种处理 singleton 类型的机制,其中类型只有一个值(或者有时存在多个值但您从不关心哪个值)。 Reifiesreify 用于配置。
猜你喜欢
  • 2015-04-09
  • 2013-04-07
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
相关资源
最近更新 更多