- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
众所周知,实现 Haskell 类型类的一种方法是通过“类型类字典”。 (这当然是 ghc 中的实现,尽管我强制说明其他实现是可能的。)为了修正想法,我将简要描述它是如何工作的。像这样的类声明
class (MyClass t) where
test1 :: t -> t -> t
test2 :: t -> String
test3 :: t
data MyClass_ t = MyClass_ {
test1_ :: t -> t -> t,
test2_ :: t -> String,
test3_ :: t,
}
instance (MyClass Int) where
test1 = (+)
test2 = show
test3 = 3
instance_MyClass_Int :: MyClass_ Int
instance_MyClass_Int = MyClass_ (+) show 3
my_function :: (MyClass t) => t -> String
my_function val = test2 . test1 test3
my_function_ :: MyClass_ t -> t -> String
my_function_ dict val = (test2_ dict) . (test1_ dict) (test3_ dict)
M
它定义了一堆具有类约束的类和函数。
M
是“不透明的”;我可以看到它导出的内容(相当于 .hi 文件),我可以从中导入,但我看不到它的源代码。我要构建一个新模块
N
它基本上导出相同的东西,但应用了上述转换。例如,如果
M
导出
class (Foo t) where
example1 :: t -> t -> t
example2 :: t -- note names and type signatures visible here
-- because they form part of the interface...
instance (Foo String) -- details of implementation invisible
instance (Foo Bool) -- details of implementation invisible
my_fn :: (Foo t) => t -> t -- exported polymorphic fn with class constraint
-- details of implementation invisible
N
会开始像
module N where
import M
data Foo_ t = Foo_ {example1_ :: t-> t -> t, example2_ :: t}
instance_Foo_String :: Foo_ String
instance_Foo_String = Foo_ example1 example2
instance_Foo_Bool :: Foo_ Bool
instance_Foo_Bool = Foo_ example1 example2
my_fn_ :: Foo_ t -> t -> t
my_fn_ = ???
my_fn
的“显式类型类”版本从原来的?这看起来相当棘手,而且令人愤怒,因为我们都知道模块 M 基本上已经在“底层”导出了类似
my_fn_
的内容。我想创建的。 (或者至少,它在 GHC 上。)
最佳答案
作为记录,我想我会解释我已经知道的“hacky”解决方案。我将基本上使用一系列示例来说明它。所以让我们想象一下,我们正在尝试具体化以下中的类、实例和函数(它们主要由非常标准的类型类组成,通常为了说明而有所简化):
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
module Src where
import Data.List (intercalate)
class SimpleShow a where
sshow :: a -> String
class SimpleMonoid a where
mempty :: a
mappend :: a -> a -> a
class SimpleFunctor f where
sfmap :: (a -> b) -> f a -> f b
instance SimpleShow Int where
sshow = show
instance SimpleMonoid [a] where
mempty = []
mappend = (++)
instance SimpleMonoid ([a], [b]) where
mempty = ([], [])
mappend (a1, b1) (a2, b2) = (a1 ++ a2, b1 ++ b2)
instance SimpleFunctor [] where
sfmap = map
show_2lists :: (SimpleShow a) => [a] -> [a] -> String
show_2lists as1 as2 = "[" ++ intercalate ", " (map sshow as1) ++ "]/["
++ intercalate ", " (map sshow as2) ++ "]"
mconcat :: (SimpleMonoid a) => [a] -> a
mconcat = foldr mappend mempty
example :: (SimpleMonoid (x, y)) => [(x, y)] -> (x, y)
example = foldr mappend mempty
lift_all :: (SimpleFunctor f) => [a -> b] -> [f a -> f b]
lift_all = map sfmap
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where
import Unsafe.Coerce
import Src
data Proxy k = Proxy
class Reifies s a | s -> a where
reflect :: proxy s -> a
newtype Magic a r = Magic (forall (s :: *). Reifies s a => Proxy s -> r)
reify :: forall a r. a -> (forall (s :: *). Reifies s a => Proxy s -> r) -> r
reify a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy
{-# INLINE reify #-}
data SimpleShow_ a = SimpleShow_ {sshow_ :: a -> String}
data SimpleMonoid_ a = SimpleMonoid_ {mempty_ :: a,
mappend_ :: a -> a -> a}
data SimpleFunctor_ f = SimpleFunctor_ {
sfmap_ :: forall a b. (a -> b) -> (f a -> f b)
}
instance_SimpleShow_Int :: SimpleShow_ Int
instance_SimpleShow_Int = SimpleShow_ sshow
instance_SimpleMonoid_lista :: SimpleMonoid_ [a]
instance_SimpleMonoid_lista = SimpleMonoid_ mempty mappend
instance_SimpleMonoid_listpair :: SimpleMonoid_ ([a], [b])
instance_SimpleMonoid_listpair = SimpleMonoid_ mempty mappend
instance_SimpleFunctor_list :: SimpleFunctor_ []
instance_SimpleFunctor_list = SimpleFunctor_ sfmap
---------------------------------------------------------------------
--code to reify show_2lists :: (SimpleShow a) => [a] -> [a] -> String
-- for each type variable that occurs in the constraints, we must
-- create a newtype. Here there is only one tpye variable ('a') so we
-- create one newtype.
newtype Wrap_a a s = Wrap_a { extract_a :: a }
-- for each constraint, we must create an instance of the
-- corresponding typeclass where the instance variables have been
-- replaced by the newtypes we just made, as follows.
instance Reifies s (SimpleShow_ a) => SimpleShow (Wrap_a a s) where
--sshow :: (Wrap_ a s) -> String
sshow = unsafeCoerce sshow__
where sshow__ :: a -> String
sshow__ = sshow_ $ reflect (undefined :: [] s)
-- now we can reify the main function
show_2lists_ :: forall a. SimpleShow_ a -> [a] -> [a] -> String
show_2lists_ dict = let
magic :: forall s. ([Wrap_a a s] -> [Wrap_a a s] -> String)
-> Proxy s -> ([a] -> [a] -> String)
magic v _ arg1 arg2 = let
w_arg1 :: [Wrap_a a s]
w_arg1 = unsafeCoerce (arg1 :: [a])
w_arg2 :: [Wrap_a a s]
w_arg2 = unsafeCoerce (arg2 :: [a])
w_ans :: String
w_ans = v w_arg1 w_arg2
ans :: String
ans = unsafeCoerce w_ans
in ans
in (reify dict $ magic show_2lists)
---------------------------------------------------------------------
--code to reify mconcat :: (SimpleMonoid a) => [a] -> a
-- Here the newtypes begin with Wrap1 to avoid name collisions with
-- the ones above
newtype Wrap1_a a s = Wrap1_a { extract1_a :: a }
instance Reifies s (SimpleMonoid_ a) => SimpleMonoid (Wrap1_a a s) where
--mappend :: (Wrap1_a a s) -> (Wrap1_a a s) -> (Wrap1_a a s)
mappend = unsafeCoerce mappend__
where mappend__ :: a -> a -> a
mappend__ = (mappend_ $ reflect (undefined :: [] s))
--mempty :: (Wrap1_a a s)
mempty = unsafeCoerce mempty__
where mempty__ :: a
mempty__ = (mempty_ $ reflect (undefined :: [] s))
mconcat_ :: forall a. SimpleMonoid_ a -> [a] -> a
mconcat_ dict = let
magic :: forall s. ([Wrap1_a a s] -> (Wrap1_a a s)) -> Proxy s -> ([a] -> a)
magic v _ arg1 = let
w_arg1 :: [Wrap1_a a s]
w_arg1 = unsafeCoerce (arg1 :: [a])
w_ans :: Wrap1_a a s
w_ans = v w_arg1
ans :: a
ans = unsafeCoerce w_ans
in ans
in (reify dict $ magic mconcat)
---------------------------------------------------------------------
--code to reify example :: (SimpleMonoid (x, y)) => [(x, y)] -> (x, y)
newtype Wrap2_x x s = Wrap2_x { extract2_x :: x }
newtype Wrap2_y y s = Wrap2_y { extract2_y :: y }
instance Reifies s (SimpleMonoid_ (x, y))
=> SimpleMonoid (Wrap2_x x s, Wrap2_y y s) where
--mappend :: (Wrap2_x x s, Wrap2_y y s) -> (Wrap2_x x s, Wrap2_y y s)
-- -> (Wrap2_x x s, Wrap2_y y s)
mappend = unsafeCoerce mappend__
where mappend__ :: (x, y) -> (x, y) -> (x, y)
mappend__ = (mappend_ $ reflect (undefined :: [] s))
--mempty :: (Wrap2_x x s, Wrap2_y y s)
mempty = unsafeCoerce mempty__
where mempty__ :: (x, y)
mempty__ = (mempty_ $ reflect (undefined :: [] s))
example_ :: forall x y. SimpleMonoid_ (x, y) -> [(x, y)] -> (x, y)
example_ dict = let
magic :: forall s. ([(Wrap2_x x s, Wrap2_y y s)] -> (Wrap2_x x s, Wrap2_y y s))
-> Proxy s -> ([(x, y)] -> (x, y))
magic v _ arg1 = let
w_arg1 :: [(Wrap2_x x s, Wrap2_y y s)]
w_arg1 = unsafeCoerce (arg1 :: [(x, y)])
w_ans :: (Wrap2_x x s, Wrap2_y y s)
w_ans = v w_arg1
ans :: a
ans = unsafeCoerce w_ans
in ans
in (reify dict $ magic mconcat)
---------------------------------------------------------------------
--code to reify lift_all :: (SimpleFunctor f) => [a -> b] -> [f a -> f b]
newtype Wrap_f f s d = Wrap_f { extract_fd :: f d}
instance Reifies s (SimpleFunctor_ f) => SimpleFunctor (Wrap_f f s) where
--sfmap :: (a -> b) -> (Wrap_f f s a -> Wrap_f f s b)
sfmap = unsafeCoerce sfmap__
where sfmap__ :: (a -> b) -> (f a -> f b)
sfmap__ = sfmap_ $ reflect (undefined :: [] s)
lift_all_ :: forall a b f. SimpleFunctor_ f -> [a -> b] -> [f a -> f b]
lift_all_ dict = let
magic :: forall s. ([a -> b] -> [Wrap_f f s a -> Wrap_f f s b])
-> Proxy s -> ([a -> b] -> [f a -> f b])
magic v _ arg1 = let
w_arg1 :: [a -> b]
w_arg1 = unsafeCoerce (arg1 :: [a -> b])
w_ans :: [Wrap_f f s a -> Wrap_f f s b]
w_ans = v w_arg1
ans :: [f a -> f b]
ans = unsafeCoerce w_ans
in ans
in (reify dict $ magic lift_all)
main :: IO ()
main = do
print (show_2lists_ instance_SimpleShow_Int [3, 4] [6, 9])
print (mconcat_ instance_SimpleMonoid_lista [[1, 2], [3], [4, 5]])
print (example_ instance_SimpleMonoid_listpair
[([1, 2], ["a", "b"]), ([4], ["q"])])
let fns' :: [[Int] -> [Int]]
fns' = lift_all_ instance_SimpleFunctor_list [\ x -> x+1, \x -> x - 1]
print (map ($ [5, 7]) fns')
{- output:
"[3, 4]/[6, 9]"
[1,2,3,4,5]
([1,2,4],["a","b","q"])
[[6,8],[4,6]]
-}
unsafeCoerce
, 但总是关联两种仅在新类型存在时不同的类型。由于运行时表示是相同的,这没关系。
关于haskell - 将具有类型类约束的函数转换为采用显式类型类字典的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22158673/
我正在尝试将一个字符串逐个字符地复制到另一个字符串中。目的不是复制整个字符串,而是复制其中的一部分(我稍后会为此做一些条件......) 但我不知道如何使用迭代器。 你能帮帮我吗? std::stri
我想将 void 指针转换为结构引用。 结构的最小示例: #include "Interface.h" class Foo { public: Foo() : mAddress((uint
这有点烦人:我有一个 div,它从窗口的左上角开始过渡,即使它位于文档的其他任何位置。我试过 usign -webkit-transform-origin 但没有成功,也许我用错了。有人可以帮助我吗?
假设,如果将 CSS3 转换/转换/动画分配给 DOM 元素,我是否可以检测到该过程的状态? 我想这样做的原因是因为我正在寻找类似过渡链的东西,例如,在前一个过渡之后运行一个过渡。 最佳答案 我在 h
最近我遇到了“不稳定”屏幕,这很可能是由 CSS 转换引起的。事实上,它只发生在 Chrome 浏览器 上(可能还有 Safari,因为一些人也报告了它)。知道如何让它看起来光滑吗?此外,您可能会注意
我正在开发一个简单的 slider ,它使用 CSS 过渡来为幻灯片设置动画。我用一些基本样式和一些 javascript 创建了一支笔 here .注意:由于 Codepen 使用 Prefixfr
我正在使用以下代码返回 IList: public IList FindCodesByCountry(string country) { var query =
如何设计像这样的操作: 计算 转化 翻译 例如:从“EUR”转换为“CNY”金额“100”。 这是 /convert?from=EUR&to=CNY&amount=100 RESTful 吗? 最佳答
我使用 jquery 组合了一个图像滚动器,如下所示 function rotateImages(whichHolder, start) { var images = $('#' +which
如何使用 CSS (-moz-transform) 更改一个如下所示的 div: 最佳答案 你可以看看Mozilla Developer Center .甚至还有例子。 但是,在我看来,您的具体示例不
我需要帮助我正在尝试在选中和未选中的汉堡菜单上实现动画。我能够为菜单设置动画,但我不知道如何在转换为 0 时为左菜单动画设置动画 &__menu { transform: translateX(
我正在为字典格式之间的转换而苦苦挣扎:我正在尝试将下面的项目数组转换为下面的结果数组。本质上是通过在项目第一个元素中查找重复项,然后仅在第一个参数不同时才将文件添加到结果集中。 var items:[
如果我有两个定义相同的结构,那么在它们之间进行转换的最佳方式是什么? struct A { int i; float f; }; struct B { int i; float f; }; void
我编写了一个 javascript 代码,可以将视口(viewport)从一个链接滑动到另一个链接。基本上一切正常,你怎么能在那里看到http://jsfiddle.net/DruwJ/8/ 我现在的
我需要将文件上传到 meteor ,对其进行一些图像处理(必要时进行图像转换,从图像生成缩略图),然后将其存储在外部图像存储服务器(s3)中。这应该尽可能快。 您对 nodejs 图像处理库有什么建议
刚开始接触KDB+,有一些问题很难从Q for Mortals中得到。 说,这里 http://code.kx.com/wiki/JB:QforMortals2/casting_and_enumera
我在这里的一个项目中使用 JSF 1.2 和 IceFaces 1.8。 我有一个页面,它基本上是一大堆浮点数字段的大编辑网格。这是通过 inputText 实现的页面上的字段指向具有原始值的值对象
ScnMatrix4 是一个 4x4 矩阵。我的问题是什么矩阵行对应于位置(ScnVector3),旋转(ScnVector4),比例(ScnVector3)。第 4 行是空的吗? 编辑: 我玩弄了
恐怕我是 Scala 新手: 我正在尝试根据一些简单的逻辑将 Map 转换为新 Map: val postVals = Map("test" -> "testing1", "test2" -> "te
输入: This is sample 1 This is sample 2 输出: ~COLOR~[Green]This is sample 1~COLOR~[Red]This is sam
我是一名优秀的程序员,十分优秀!