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

Din*_*uek 9 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
Run Code Online (Sandbox Code Playgroud)

给我一个错误:

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
Run Code Online (Sandbox Code Playgroud)

但是这个

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
Run Code Online (Sandbox Code Playgroud)

编译.

为什么?

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

aug*_*tss 11

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

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


ham*_*mar 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
Run Code Online (Sandbox Code Playgroud)

但是,在大多数情况下,将约束放在函数上是正确的.