有人可以用*非常*简单的术语解释反射包 API 吗?

Posted

技术标签:

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

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

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

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

【问题讨论】:

黑线鳕页面链接的教程有帮助吗:schoolofhaskell.com/user/thoughtpolice/using-reflection? 相关:***.com/a/29929718/1364288 ***.com/a/28651952/1364288 请注意,“反射”是一种高级技术,它依赖于 GHC 内部工作特性的当前实现。这不是适合初学者/中级用户的技术。 【参考方案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 用于配置。

以上是关于有人可以用*非常*简单的术语解释反射包 API 吗?的主要内容,如果未能解决你的问题,请参考以下文章

有人可以帮助解释这个回溯算法中的递归吗?

有人可以为我非常简单地解释 MVC 吗? [复制]

java中的数据源是啥?有人可以用简单的语言解释一下吗?

外行术语中的同源策略

用外行术语来说,pytorch 中的聚集函数有啥作用?

pathos:并行处理选项 - 有人可以解释其中的差异吗?