gpt4 book ai didi

haskell - 我们可以抽象类型类吗?

转载 作者:行者123 更新时间:2023-12-04 16:27:09 25 4
gpt4 key购买 nike

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

例如,当我们有

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]


nzip :: (Num b, Num c) => (forall a.Num a => [a] -> [a]) -> [b] -> [c] -> [(b,c)]
nzip f xs ys = zip (f xs) (f ys)

但是我们不能归并不是很尴尬 ezipnzip像这样:
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 的正确实例化不靠别人帮助。

关于haskell - 我们可以抽象类型类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34029594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com