gpt4 book ai didi

haskell - 多元广义和

转载 作者:行者123 更新时间:2023-12-03 22:09:56 25 4
gpt4 key购买 nike

This answer演示了一个对其参数求和的多变量函数:

class SumRes r where 
sumOf :: Integer -> r

instance SumRes Integer where
sumOf = id

instance (Integral a, SumRes r) => SumRes (a -> r) where
sumOf x = sumOf . (x +) . toInteger
我已经为 Num 的所有成员创建了这个函数的通用版本。 :
class (Num n) => MySumType n r where
mySum :: n -> r

instance (Num n) => MySumType n n where
mySum x = x

instance (Num n, MySumType n r) => MySumType n (n->r) where
mySum x = mySum . (x +)
然而,这只适用于像 mySum (1::Int) (3::Int) (2::Int) :: Int 这样的调用。 .如果没有参数上的类型说明符,我会收到此错误:

No instance for (MySumType n0 Float) arising from a use of `mySum'

Possible fix: add an instance declaration for (MySumType n0 Float)

In the expression: mySum 1.0 :: Float

In an equation for `it': it = mySum 1.0 :: Float


是什么导致了这个问题,我该如何解决?我怀疑这与整数文字的类型有关 Num a => a .还有与上述不依赖扩展的等效功能吗?上面使用的是多参数类型类和灵活实例。

最佳答案

到目前为止,我还没有在 haskell 中遇到一个令人信服的多变量函数用例,这无法通过使用列表或类似的数据结构来解决。所以如果你认为你有一个超越新奇的东西,我和他们一起玩的原因,我会很高兴知道它是什么。下面给出了足够多的例子,其中一些是我在发表评论时应该想到的,我已经撤回了我的声明。

{-# language MultiParamTypeClasses #-}
{-# language FlexibleInstances #-}
{-# language TypeFamilies #-}
{-# language IncoherentInstances #-}

class (Num n) => MySumType n r where
mySum :: n -> r

instance (Num n, m~n) => MySumType n m where
mySum x = x

instance (Num n, MySumType n r, n~m) => MySumType n (m->r) where
mySum x = mySum . (x +)

然后将文件加载到 ghci 后:
> mySum 1 2 4 5 6 7 :: Int
25
> mySum 1.1 2 4.6 5 6.9 7 :: Double
26.6

在某些情况下,类型推断也可以成为您的 friend ,允许您删除最终类型注释,如以下人为情况:
> replicate (mySum 1 2 3 4) 6
[6,6,6,6,6,6,6,6,6,6]

关于:

Also is there an equivalent function to the one above that does not rely on extensions?



我觉得你运气不好。我想指出,除非您有理由离开 GHC 或继续使用 Haskell98 或 Haskell2010,否则扩展不会对您造成伤害并且几乎不会造成兼容性问题,因为大多数人似乎都在使用 GHC。

编辑:附加说明

让我们开始解释简单实例之间的区别。我将为我提供的一些实现名称添加后缀 2。
instance (Num n) => MySumType n n where
mySum x = x

如果将其与类声明结合使用:
class (Num n) => MySumType n r where
mySum :: n -> r
mySum类型签名为 mySum :: (Num n) => n -> n .那 n -> n说的是一个 1 arity 函数,它采用类型 n , 产生 nn有一类 Num。

使用时 mySum我必须指定我给它的东西和它产生的东西。
mySum 1 :: Int
mySum (1 :: Int)

只有在指定输入和输出类型时才会给出错误,它会给出结果:
mySum (1 :: Int) :: Int
^ ^
| specify output type
specify input type

产生一个结果(在这种情况下为 1)。这是因为您已经为 n -> n 提供了一个实例。但有人可以稍后为 n -> m 添加一个实例如 Int -> Double如下所示:
instance MySumType Int Double where
mySum x = 2 * fromIntegral x

> mySum (1::Int) :: Int
1
> mySum (1::Int) :: Double
2.0

这些实例每个都匹配所有可能的 1 arity 函数类型的非常窄的范围。

现在让我们看看修改后的版本
instance (Num n, m~n) => MySumType n m where
mySum x = x
mySum这里有类型签名 mySum :: (Num n, m~n) => n -> m此类型签名适用于所有 1 个采用类型 n 的arity 函数并生成类型 m在哪里 n有类 Num 和 m等于 n .请注意,这开始匹配所有 1 元函数, n -> m , 任意 n任何 m然后把它放在上面。

现在可以这样做:
> mySum2 (1::Int)
1
> mySum2 1 :: Int
1

一旦指定了输入,也指定了输出。其他说明 1 , 2 .

这不会阻止我们指定更具体的实例,例如 Int -> Double像以前一样:
instance MySumType Int Double where
mySum x = 2 * fromIntegral x

> mySum2 1 :: Int
1
> mySum2 1 :: Double
1.0
> mySum2 (1 :: Int) :: Double
2.0

只有最后一个 mySum2正在关闭 Int -> Double实例。这是 IncoherentInstances 的属性我想我会把它留给 another stackoverflow question回答角色 IncoherentInstances正在玩。

关于haskell - 多元广义和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16307399/

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