部分应用数据构造函数

gog*_*urt 4 haskell currying partial-application

我不明白为什么以下练习在第一原理的Haskell编程中 "有效" :

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

将其加载到ghci中表明它可以很好地解决问题,但为什么定义s1甚至有意义呢?我仍然是Haskell的新手,所以起初我认为这是因为在s1Haskell中隐含地让Object字符串为空.但是之后...

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

我还在学习如何正确解释这些错误信息,所以请耐心等待.但有人能解释一下是什么No instance for (Show (Object -> Sentence))意思吗 更具体地讲,如何留出的Object字符串s1结果在这(Object -> Sentence)件事?

我确信这很简单,但我觉得这本书让我无法理解这一点......

Eri*_*ikR 8

但为什么s1甚至有意义的定义呢?

正如@Alec所说,这叫做currying.查看正在发生的事情的一种方法是让GHCI告诉您它的类型s1:

ghci> :t s1
s1 :: Object -> Sentence
Run Code Online (Sandbox Code Playgroud)

所以s1是服用功能ObjectSentence.另一种思考方式是从定义开始:

s1 = Sentence "dogs" "drool"
Run Code Online (Sandbox Code Playgroud)

并使用等式推理将双方应用于一个值x:

s1 x = Sentence "dogs" "drool" x
Run Code Online (Sandbox Code Playgroud)

所以,当你调用s1 x它与调用Sentence与前两个函数的参数硬编码为"dogs""drool",并x成为第三个参数的Sentence功能.

谁能解释一下"没有实例(Show (Object -> Sentence))"意味着什么?

当您评估GHCI中的某些内容时,它与向Haskell提出的内容基本相同print.那是,

ghci> 3+4
Run Code Online (Sandbox Code Playgroud)

实际上与以下内容相同:

ghci> print (3+4)
Run Code Online (Sandbox Code Playgroud)

(此规则不适用于IO操作getLine,甚至print本身.在这些情况下,Haskell只运行IO操作.)

为了print某些东西,必须有一个类型的Show实例.但正如我们上面所看到的,s1是类型的函数Object -> Sentence,并且没有为函数预定义的Show实例.

请注意,有一个Show实例用于Sentence值,因为您要求GHC派生一个deriving (Eq, Show).因此,当您在GHCI提示符下键入时:

ghci> Sentence "Julie" "loves" "dogs"
Run Code Online (Sandbox Code Playgroud)

你回来了:

Sentence "Julie" "loves" "dogs"
Run Code Online (Sandbox Code Playgroud)

因为你真的要求GHCI运行print (Sentence "Julie" "loves" "dogs").

请注意,print它本身定义为(链接):

print x = putStrLn (show x)
Run Code Online (Sandbox Code Playgroud)

并且调用show是为什么值需要为其定义Show实例才能打印它.