gpt4 book ai didi

haskell - 是否可以在 Haskell 中编码一个通用的 "lift"函数?

转载 作者:行者123 更新时间:2023-12-04 00:13:20 24 4
gpt4 key购买 nike

我不是可变参数的最大粉丝,但我一直认为应用( f <$> x <*> y )和成语( [i| f x y |] )样式都有太多符号。我通常更喜欢 liftA2 f x y方式,但我也认为A2有点丑。来自 this question ,我了解到可以在 Haskell 中实现 vararg 函数。这样,是否可以使用相同的原理来实现提升功能,例如:

lift f a b == pure f <*> a <*> b

我试过替换 +通过 <*>在引用的代码上:
class Lift r where 
lift :: a -> r

instance Lift a where
lift = id

instance (Lift r) => Lift (a -> r) where
lift x y = lift (x <*> y)

但我无法设法让类型正确......

最佳答案

请注意,您可以链接任意数量的 <*> , 得到形式的函数

f (a0 -> .. -> an) -> (f a0 -> .. -> f an)

如果我们有类型 a0 -> .. -> anf a0 -> .. -> f an , 我们可以计算 f由此。我们可以编码这种关系,以及最一般的类型,如下
class Lift a f b | a b -> f where 
lift' :: f a -> b

如您所料,“递归案例”实例将简单地应用 <*>一次,然后递归:
instance (a ~ a', f' ~ f, Lift as f rs, Applicative f) 
=> Lift (a -> as) f (f' a' -> rs) where
lift' f a = lift' $ f <*> a

基本情况是没有更多功能时。由于您实际上不能断言“ a 不是函数类型”,因此这依赖于重叠实例:
instance (f a ~ b) => Lift a f b where 
lift' = id

由于 GHC 的实例选择规则,如果可能,将始终选择递归案例。

那么你想要的函数是 lift' . pure :
lift :: (Lift a f b, Applicative f) => a -> b
lift x = lift' (pure x)

这是对 Lift 的功能依赖的地方。变得非常重要。由于 f仅在上下文中提及,除非我们能够确定 f只知道 ab (确实出现在 => 的右侧)。

这需要几个扩展:
{-# LANGUAGE 
OverlappingInstances
, MultiParamTypeClasses
, UndecidableInstances
, FunctionalDependencies
, ScopedTypeVariables
, TypeFamilies
, FlexibleInstances
#-}

并且,与 Haskell 中的可变参数函数一样,通常选择实例的唯一方法是给出显式类型签名。
lift (\x y z -> x * y + z) readLn readLn readLn :: IO Int

我写的方式,GHC会很乐意接受 liftf 的参数中是多态的(但不是 f 本身)。
lift (+) [1..5] [3..5] :: (Enum a, Num a) => [a]

有时上下文足以推断出正确的类型。请注意,参数类型也是多态的。
main = lift (\x y z -> x * y + z) readLn readLn readLn >>= print 

从 GHC >= 7.10 开始, OverlappingInstances已被弃用,编译器将发出警告。它可能会在以后的某个版本中被删除。这可以通过删除 OverlappingInstances 来解决。来自 {-# LANGUAGE .. #-} pragma 并将第二个实例更改为
instance {-# OVERLAPS #-} (f a ~ b) => Lift a f b where 

关于haskell - 是否可以在 Haskell 中编码一个通用的 "lift"函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28003135/

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