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

Age*_*uid 7 reflection proxy haskell reify

我很难理解描述反射包的文档/示例。我是命令式编程的老手,但还是 Haskell 新手。你能带我做一个非常简单的介绍吗?

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

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

K. *_*uhr 7

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

data Config = Config { w :: Int, s :: String }
Run Code Online (Sandbox Code Playgroud)

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

timesW :: (Given Config) => Int -> Int
Run Code Online (Sandbox Code Playgroud)

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

timesW x = w given * x
Run Code Online (Sandbox Code Playgroud)

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

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

foo :: (Given Config) => Int -> String
foo n = copies (timesW n) (s given)
Run Code Online (Sandbox Code Playgroud)

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

main = do
  print $ give (Config 5 "x") $ foo 3
  print $ give (Config 2 "no") $ foo 4
Run Code Online (Sandbox Code Playgroud)

这类似于:

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

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

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

    timesW x = (*) <$> asks w <*> pure x
    foo n = copies <$> timesW n <*> asks s
    
    Run Code Online (Sandbox Code Playgroud)

完整示例:

{-# 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
Run Code Online (Sandbox Code Playgroud)