What does has kind 'Constraint' mean in Haskell

前端 未结 2 647
孤街浪徒
孤街浪徒 2021-02-15 15:16

I am fresh to Haskell and I am trying to understand the language by writing some code. I am only familiar with very simple instructions on ghci: head, tail, sum, (*), and the li

相关标签:
2条回答
  • 2021-02-15 15:31

    A few things to adjust:

    0) mod isn't a good name for your function, as it is the name of the modulo function from the standard library. I will call it norm instead.

    1) The type signature you meant to write is:

    norm :: Num a => [a] -> a
    

    [a] is the type of a list with elements of type a. The Num a before the => isn't a type, but a constraint, which specifies that a must be a number type (or, more accurately, that it has to be an instance of the Num class). [Num a] => leads to the error you have seen because, given the square brackets, the type checker takes it as an attempt to use a list type instead of a constraint.

    Beyond the Num a issue, you have left out the result type from the signature. The corrected signature reflects that your function takes a list of numbers and returns a number.

    2) The Num a constraint is too weak for what you are trying to do. In order to use sqrt, you need to have not merely a number type, but one that is an instance of Floating (cf. leftaroundabout's comment to this answer):

    GHCi> :t sqrt
    sqrt :: Floating a => a -> a
    

    Therefore, your signature should be

    norm :: Floating a => [a] -> a
    

    3) [x] is a list with a single element, x. If your argument is already a list, as the type signature says, there is no need to enclose it in square brackets. Your function, then, becomes:

    norm :: Floating a => [a] -> a
    norm x = sqrt a
        where a = sum b
                where b = map sq x
    

    Or, more neatly, without the second where-block:

    norm :: Floating a => [a] -> a
    norm x = sqrt (sum b)
        where b = map sq x
    
    0 讨论(0)
  • 2021-02-15 15:39

    As you are aware, values can be classified by their type. "foo" has type [Char], Just 'c' has type Maybe Char, etc.

    Similarly, types can be classified by their kind. All concrete types for which you can provide a value have kind *. You can see this using the :k command in GHCi:

    > :k Int
    Int :: *
    > :k Maybe Int
    Maybe Int :: *
    

    Type constructors also have kinds. They are essentially type-valued functions, so their kinds are similar to regular functions.

    > :t id
    id :: a -> a
    > :k Maybe
    Maybe :: * -> *
    

    But what is Num a? It's not a type, so it doesn't have kind *. It's not a type constructor, so it doesn't have an arrow kind. It is something new, so a new kind was created to describe it.

    > :k Num Int
    Num Int :: Constraint
    

    And Num itself is a Constraint-valued function: it takes a value of kind * and produces a Constraint:

    > :k Num
    Num :: * -> Constraint
    

    A thing with kind Constraint is used to specify the typeclass that a particular type must be an instance of. It is the value that can occur before => in a type signature. It is also the "argument" to the instance "function":

    instance Num Int where
      ...
    
    0 讨论(0)
提交回复
热议问题