Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial application of data constructor

I don't understand why the following exercise "works" in Haskell Programming from First Principles:

type Subject = String
type Verb = String
type Object = String

data Sentence =
    Sentence Subject Verb Object
    deriving (Eq, Show)

s1 = Sentence "dogs" "drool"
s2 = Sentence "Julie" "loves" "dogs"

Loading this into ghci shows that it typechecks just fine, but why is it that the definition of s1 even makes sense? I'm still very new to Haskell, so at first I thought this was because in s1 Haskell was implicitly letting the Object string be empty. But then...

*Main> s1

<interactive>:13:1:
    No instance for (Show (Object -> Sentence))
      arising from a use of `print'
    Possible fix:
      add an instance declaration for (Show (Object -> Sentence))
    In a stmt of an interactive GHCi command: print it

I'm still learning how to properly interpret these error messages, so please bear with me. But can someone explain what No instance for (Show (Object -> Sentence)) means? More specifically, how does leaving out the Object string in s1 result in this (Object -> Sentence) thing?

I'm sure this is stupid easy, but I don't think the book has equipped me to understand this by this point...

like image 397
gogurt Avatar asked Feb 06 '23 06:02

gogurt


1 Answers

but why is it that the definition of s1 even makes sense?

As @Alec mentioned, it's called currying. One way to see what is going on is to have GHCI tell you what the type of s1 is:

ghci> :t s1
s1 :: Object -> Sentence

So s1 is a function taking an Object to a Sentence. Another way to think about is to start with the definition:

s1 = Sentence "dogs" "drool"

and using equational reasoning apply both sides to a value x:

s1 x = Sentence "dogs" "drool" x

So when you call s1 x it's the same as calling Sentence with the first two function arguments hard-coded to "dogs" and "drool", and x becomes the third argument to the Sentence function.

can someone explain what "No instance for (Show (Object -> Sentence))" means?

When you evaluate something in GHCI is it basically the same as asking Haskell to print it. That is,

ghci> 3+4

is effectively the same as:

ghci> print (3+4)

(This rule doesn't apply to IO-actions like getLine or even print itself. In those cases Haskell just runs the IO-action.)

In order to print something there has to be a Show instance for the type. But as we've seen above, s1 is a function of type Object -> Sentence, and there are no predefined Show instances for functions.

Note that there is a Show instance for Sentence values because you asked GHC to derive one with deriving (Eq, Show). So when you type at the GHCI prompt:

ghci> Sentence "Julie" "loves" "dogs"

you get back:

Sentence "Julie" "loves" "dogs"

because you are really asking GHCI to run print (Sentence "Julie" "loves" "dogs").

Note that print itself is defined as (link):

print x = putStrLn (show x)

and the call to show is the reason why a value needs to have a Show instance defined for it in order to print it.

like image 144
ErikR Avatar answered Feb 08 '23 20:02

ErikR