有人可以用*非常*简单的术语解释反射包 API 吗?
Can some explain the reflection package API in *very* simple terms?
我很难理解那里描述反射包的 documentation/examples。我是命令式编程的老手,但是 Haskell 新手。你能给我简单介绍一下吗?
包裹:https://hackage.haskell.org/package/reflection
编辑:对于关闭此问题的人:这是 Haskell 反射的入门介绍。下面的答案很好,其他的也有用,所以请重新打开。
在最简单的用例中,如果您有一些配置信息希望在一组函数中普遍可用:
data Config = Config { w :: Int, s :: String }
您可以为需要访问配置的函数添加一个Given Config
约束:
timesW :: (Given Config) => Int -> Int
然后使用值 given
来引用当前配置(因此 w given
或 s 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
我很难理解那里描述反射包的 documentation/examples。我是命令式编程的老手,但是 Haskell 新手。你能给我简单介绍一下吗?
包裹:https://hackage.haskell.org/package/reflection
编辑:对于关闭此问题的人:这是 Haskell 反射的入门介绍。下面的答案很好,其他的也有用,所以请重新打开。
在最简单的用例中,如果您有一些配置信息希望在一组函数中普遍可用:
data Config = Config { w :: Int, s :: String }
您可以为需要访问配置的函数添加一个Given Config
约束:
timesW :: (Given Config) => Int -> Int
然后使用值 given
来引用当前配置(因此 w given
或 s 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