- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Haskell 中, Proxy是一个类型见证值,可以轻松传递某些类型
data Proxy a = Proxy
json-schema 中有一个使用示例:
class JSONSchema a where
schema :: Proxy a -> Schema
因此您可以执行 schema (Proxy::Proxy (Int,Char))
来获取 Int-Char-Tuple 的 JSON 表示形式(可能是一个数组)。
人们为什么使用代理?在我看来,同样可以通过以下方式实现
class JSONSchema a where
schema :: Schema a
与Bounded
类型类的工作方式类似。我首先认为使用代理时获取某些给定值的模式可能更容易,但事实似乎并非如此:
{-# LANGUAGE ScopedTypeVariables #-}
schemaOf :: JSONSchema a => a -> Schema a
schemaOf (v :: x) = schema (Proxy :: Proxy x) -- With proxy
schemaOf (v :: x) = schema :: Schema x -- With `:: a`
schemaOf _ = schema -- Even simpler with `:: a`
此外,人们可能会担心 Proxy
值是否实际上在运行时被消除,这是一个优化问题,而使用 ::a
方法时则不存在.
如果Bounded
采用的::a
方法可以用更短的代码实现相同的结果,并且不用担心优化,那么为什么人们还要使用代理呢? 代理有什么好处?
编辑:一些答案和评论者正确地指出 ::a
方法用 a 污染了 data Schema = ...
类型“无用”类型参数 - 至少从普通数据结构本身的角度来看,它从不使用 a
( see here )。
建议使用幻像类型Tagged s b
相反,它允许分离两个关注点(Tagged a Schema
将非参数模式类型与类型变量 a
结合起来),这比 ::一种
方法。
所以我的问题应该是代理与标记方法相比有什么好处?
最佳答案
两个示例,一个需要 Proxy
,另一个示例 Proxy
不会从根本上改变类型,但我还是倾向于使用它。
代理
必要Proxy
或一些等效的技巧是必要的。也许中间类型改变了语义,例如 read 。显示::字符串->字符串
。启用 ScopedTypeVariables
后,我会写
f :: forall proxy a. (Read a, Show a) => proxy a -> String -> String
f _ = (show :: a -> String) . read
> f (Proxy :: Proxy Int) "3"
"3"
> f (Proxy :: Proxy Bool) "3"
"*** Exception: Prelude.read: no parse
代理参数允许我将a
公开为类型参数。 显示 . read
是一个愚蠢的例子。更好的情况可能是某些算法在内部使用通用集合,其中所选的集合类型具有一些您希望消费者能够控制的性能特征,而不需要(或允许)他们提供或接收中间值。
像这样,使用 fgl
类型,我们不想想要公开内部Data
类型。 (也许有人可以为这个例子建议一个合适的算法?)
f :: Input -> Output
f = g . h
where
h :: Gr graph Data => Input -> graph Data
g :: Gr graph Data => graph Data -> Output
公开代理参数将允许用户在 Patricia 树或普通 TreeMap 实现之间进行选择。
代理
作为 API 或实现便利我有时使用Proxy
作为选择类型类实例的工具,特别是在递归或归纳类实例中。考虑我在 this answer about using nested Either
s 中编写的 MightBeA
类:
class MightBeA t a where
isA :: proxy t -> a -> Maybe t
fromA :: t -> a
instance MightBeA t t where
isA _ = Just
fromA = id
instance MightBeA t (Either t b) where
isA _ (Left i) = Just i
isA _ _ = Nothing
fromA = Left
instance MightBeA t b => MightBeA t (Either a b) where
isA p (Right xs) = isA p xs
isA _ _ = Nothing
fromA = Right . fromA
这个想法是从Either String (Either Bool Int)
中提取一个Maybe Int
。 isA
的类型基本上是 a -> Maybe t
。这里使用代理有两个原因:
首先,它消除了消费者的类型签名。您可以将 isA
调用为 isA (Proxy::Proxy Int)
,而不是 isA::MightBeA Int a => a -> Maybe Int
。
其次,通过传递代理,我可以更轻松地思考归纳案例。使用 ScopedTypeVariables,可以在没有代理参数的情况下重写该类;归纳情况将实现为
instance MightBeA' t b => MightBeA' t (Either a b) where
-- no proxy argument
isA' (Right xs) = (isA' :: b -> Maybe t) xs
isA' _ = Nothing
fromA' = Right . fromA'
在这种情况下,这并不是一个很大的变化;如果 isA
的类型签名要复杂得多,那么使用代理将会是一个很大的改进。
当专门为了实现方便而使用时,我通常会导出一个包装函数,这样用户就不需要提供代理。
代理
与标记
在我的所有示例中,类型参数 a
不会为输出类型本身添加任何有用的内容。 (在前两个示例中,它与输出类型无关;在最后一个示例中,它是输出类型的冗余。)如果我返回一个Tagged a x
,则消费者总是会立即取消它的标记。此外,用户必须完整地写出x
的类型,这有时非常不方便,因为它是一些复杂的中间类型。 (也许someday we'll be able to use _
in type signatures...)
(我有兴趣听到关于这个子问题的其他答案;我实际上从未使用 Tagged
编写过任何内容(没有使用 Proxy
快速重写它) )并想知道我是否遗漏了一些东西。)
关于Haskell:为什么使用代理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27044209/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!