类型约束:可以从函数参数的数据类型中推断出它们吗?

时间:2011-07-04 15:44:08

标签: haskell

newtype ( Show a , Show b , Show c ) => T a b c = T Int
t :: T a b c -> a -> b -> c -> String
t ( T x ) a b c = show a ++ show b ++ show c

给了我一个错误:

No instance for (Show c)
      arising from a use of `show'
    In the second argument of `(++)', namely `show c'
    In the second argument of `(++)', namely `show b ++ show c'
    In the expression: show a ++ show b ++ show c

但是这个

newtype ( Show a , Show b , Show c ) => T a b c = T Int
t :: ( Show a , Show b , Show c ) => T a b c -> a -> b -> c -> String
t ( T x ) a b c = show a ++ show b ++ show c

编译。

为什么?

在第一种情况下,“T a b c”是否已经暗示“(显示a,显示b,显示c)”?为什么有必要明确指定约束?

2 个答案:

答案 0 :(得分:11)

不,在数据(newtype)定义上放置上下文从来没有像人们预期的那样完成。它只在构造值时更改构造函数的类型,在模式匹配时不会发生任何新的情况。这是一个基本无用的功能,它已在最新版本的Haskell中删除。

您期望的是非常合理的,但这不是数据类型上下文的作用。

答案 1 :(得分:10)

@augustss所说的是正确的,但你可以使用GADT实现类似的东西。

{-# LANGUAGE GADTs #-}

data T a b c where
  T :: (Show a, Show b, Show c) => Int -> T a b c

t :: T a b c -> a -> b -> c -> String
t (T x) a b c = show a ++ show b ++ show c

然而,在大多数情况下,将约束放在函数上是正确的。