简体   繁体   English

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

[英]Can some explain the reflection package API in *very* simple terms?

I'm having a hard time understanding the documentation/examples out there describing the reflection package.我很难理解描述反射包的文档/示例。 I'm an imperative-programming veteran but a Haskell newb.我是命令式编程的老手,但还是 Haskell 新手。 Can you walk me through a very simple introduction?你能告诉我一个非常简单的介绍吗?

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

Edit: to whoever closed this question: this is meant to be a beginner introduction to Haskell reflection.编辑:致关闭这个问题的人:这是对 Haskell 反射的初学者介绍。 The answer below is excellent and others would be useful too, so please reopen.下面的答案很好,其他的也很有用,所以请重新打开。

In the simplest use-case, if you have some configuration information you'd like to make generally available across a set of functions:在最简单的用例中,如果您有一些配置信息,您希望在一组功能中普遍可用:

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

you can add a Given Config constraint to the functions that need access to the configuration:您可以向需要访问配置的函数添加Given Config约束:

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

and then use the value given to refer to the current configuration (and so w given or s given to refer to its fields):然后使用given的值来指代当前配置(因此w givens given指的是其字段):

timesW x = w given * x

With a few other functions, some that use the configuration and some that don't:还有一些其他功能,有些使用配置,有些不使用:

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

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

you can then run a computation under different configurations that you give :然后,您可以在您give不同配置下运行计算:

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

This is similar to:这类似于:

  • defining given :: Config globally, except you can run the computation under multiple configurations in the same program;全局定义given :: Config ,除非您可以在同一程序中的多个配置下运行计算;

  • passing the configuration around as an extra parameter to every function, except you avoid the bother of explicitly accepting the configuration and passing it on, like:将配置作为额外参数传递给每个函数,除非您避免显式接受配置并将其传递,例如:

     timesW cfg x = w cfg * x foo cfg n = copies (timesW cfg n) (s cfg)
  • using a Reader monad, but you don't have to lift everything to an awkward monad- or applicative-level syntax, like:使用Reader monad,但您不必将所有内容都提升为笨拙的 monad 或应用程序级别的语法,例如:

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

The full example:完整示例:

{-# 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM