到目前为止,我还没有在 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
在某些情况下,类型推断也可以成为您的朋友,允许您删除最终类型注释,例如在以下人为情况下:
> replicate (mySum 1 2 3 4) 6
[6,6,6,6,6,6,6,6,6,6]
关于:
还有与上述不依赖扩展的等效功能吗?
我觉得你运气不好。我想指出,除非您有理由离开 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 函数采用 type n
,产生 ann
并n
具有 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 arity 函数采用类型n
并产生类型m
,其中n
具有类 Num 并且m
等于n
。请注意,这开始于匹配所有 1 arity 函数,n -> m
, anyn
到 anym
然后将它放在上面。
现在可以这样做:
> 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
我想我会把它留给另一个 stackoverflow 问题来回答IncoherentInstances
正在扮演的角色。