开发者

Type Constraints : Can they be inferred from the datatype of a function's arguments?

开发者 https://www.devze.com 2023-03-17 08:53 出处:网络
This newtype ( Show a , Show b , Show c ) => T a b c = T Int t :: T a b c -> a -> b -> c -> String

This

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

gives me an error:

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 ++ s开发者_Python百科how c

But this

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

compiles.

Why?

In the first case, doesn't "T a b c" already imply that "( Show a , Show b , Show c )"? Why is it necessary to explicitly specify the constraint?


No, putting a context on a data (newtype) definition never did quite what one might expect. It only changes the type of the constructor when constructing values, nothing new happens when pattern matching. It's a basically useless feature and it has been removed in the latest version of Haskell.

What you expect is quite reasonable, but it's not what data type contexts do.


What @augustss said is correct, however you can achieve something similar using GADTs.

{-# 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

In most cases, however, putting the constraint on the function is the right thing to do.

0

精彩评论

暂无评论...
验证码 换一张
取 消