Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 我们可以抽象类型类吗?_Haskell - Fatal编程技术网

Haskell 我们可以抽象类型类吗?

Haskell 我们可以抽象类型类吗?,haskell,Haskell,我想知道是否有更深层次的原因,我们不能抽象类型类(或者我们可以?) 例如,当我们 fzip :: (forall a.[a] -> [a]) -> [b] -> [c] -> [(b,c)] fzip f xs ys = zip (f xs) (f ys) 那么我们可以说 fzip (drop 42) [1..100] ['a'..'z'] fzip reverse [1..100] ['a'..'z'] 等等。但我们不能 fzip (map succ) [1..

我想知道是否有更深层次的原因,我们不能抽象类型类(或者我们可以?)

例如,当我们

fzip :: (forall a.[a] -> [a]) -> [b] -> [c] -> [(b,c)]
fzip f xs ys = zip (f xs) (f ys)
那么我们可以说

fzip (drop 42) [1..100] ['a'..'z']
fzip reverse   [1..100] ['a'..'z']
等等。但我们不能

fzip (map succ) [1..100] ['a'..'z']
我们可以通过以下方式解决:

ezip :: (Enum b, Enum c) => (forall a.Enum a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
ezip f xs ys = zip (f xs) (f ys)
同样地,我们也可以解决这个问题

fzip (map (5*)) [1..100] [1.5, 2.3, 4.7]

但是,我们不能将
ezip
nzip
归为以下内容,这不是很尴尬吗

gzip :: (g b, g c) => (forall a. g a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
虽然代码完全相同,但直到类名为止? 或者我们能不能

有趣的是,当实例只是包含函数的记录时,这是很容易做到的。

您几乎可以使用
ConstraintKinds

{-# LANGUAGE ConstraintKinds, RankNTypes #-}

import Data.Proxy

gzip :: (g b, g c) => Proxy g -> (forall a . g a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
gzip _ f xs ys = zip (f xs) (f ys)

test1 = gzip (Proxy :: Proxy Enum) (map succ) [1 .. 100] ['a' .. 'z']
test2 = gzip (Proxy :: Proxy Num) (map (5*)) [1 .. 100] [1.5, 2.3, 4.7]
主要区别在于您需要
Proxy
参数,因为GHC无法在没有帮助的情况下推断
g
的正确实例化。

为约束添加一个参数:

{-# LANGUAGE PartialTypeSignatures #-}

import Data.Proxy

gzip :: (g b, g c) => Proxy g -> (forall a. g a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
gzip _ f bs cs = zip (f bs) (f cs)

> gzip (Proxy :: _ Enum) [0, 1] "ab"
[(1,'b'),(2,'c')]

GHC认为仅出现在约束中的约束参数是不明确的,因此我们需要在代理中显式记录它们。

GHC的
约束
系统期望可解性是*单态可判定的(所有带有种类
约束
的类型都由一个或多个已知类型预测-也就是说,typeclass高层结构在其typeclass标头中不能是可变的),我认为这可能是
PartialTypeSignatures
@kosmikus的一个有趣用法。我厌倦了双重代理:pye。我一定会记住这一点。尽管我仍然不太喜欢
PartialTypeSignatures
在某种程度上将类型级漏洞与类型级代码推理混为一谈。我希望它们在语法上有所不同nt与Agda类似。我希望GHC 8.0中的显式类型应用程序能够让我们彻底摆脱
Proxy
KProxy
(我想知道当前的“不明确类型”错误会发生什么)。是的,希望会有很多新的可能性:)
{-# LANGUAGE PartialTypeSignatures #-}

import Data.Proxy

gzip :: (g b, g c) => Proxy g -> (forall a. g a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
gzip _ f bs cs = zip (f bs) (f cs)

> gzip (Proxy :: _ Enum) [0, 1] "ab"
[(1,'b'),(2,'c')]