如何在haskell newtype中定义一个函数?

时间:2015-05-10 14:02:15

标签: haskell newtype type-signature

我正在尝试破解haskell中newtype的记录语法,当newtype中有一个函数时,我的理解就会中断。考虑这个简单的例子

newtype C a b = C { getC :: (a -> b) -> a }

根据我的推理,C是一个在其构造函数中接受函数和参数的类型。 所以,

let d1 = C $ (2 *) 3 

:t d1也提供了

d1 :: Num ((a -> b) -> a) => C a b

再次检查一下,我做了:t getC d1,显示了这个

getC d1 :: Num ((a -> b) -> a) => (a -> b) -> a

如果我尝试getC d1,为什么会出错? getC应返回函数及其参数或至少应用参数。

我不能拥有newtype C a b = C { getC :: (a->b)->b } deriving (Show),因为这没有意义!

2 个答案:

答案 0 :(得分:3)

  

根据我的推理,C是一种接受函数和参数的类型

怎么样?构造函数只有一个参数。 Newtypes总是只有一个构造函数,只有一个参数。

类型C,otoh,有两个类型参数。但这与您可以应用于构造函数的参数数量无关。

答案 1 :(得分:2)

总是很好的是要强调Haskell有两个完全独立的命名空间,类型语言值语言。在你的情况下,有

  • 一种类型构造函数import win32ui from pywin.mfc import object import dde class MySystemTopic(object.Object): def __init__(self): object.Object.__init__(self, dde.CreateServerSystemTopic()) def Exec(self, cmd): print "System Topic asked to exec", cmd class MyOtherTopic(object.Object): def __init__(self, topicName): object.Object.__init__(self, dde.CreateTopic(topicName)) def Exec(self, cmd): print "Other Topic asked to exec", cmd class MyRequestTopic(object.Object): def __init__(self, topicName): topic = dde.CreateTopic(topicName) topic.AddItem(dde.CreateStringItem("")) object.Object.__init__(self, topic) def Request(self, aString): print "Request Topic sent: ", aString a="UP0 DN145800001 UMusb DMfm AZ040 EL005 SNNO SATELLITE" print a return(a) server = dde.CreateServer() server.AddTopic(MyRequestTopic("Tracking")) server.Create('Orbitron') while 1: win32ui.PumpWaitingMessages(0, -1) ,它以类型语言存在。它需要两种类型C :: * -> * -> *a(种类b)并将它们映射到类型*(也属于C a b类型)。
  • 值构造函数*,它以值语言存在。它需要一个C :: ((a->b) -> a) -> C a b函数(f类型)并将其映射到值(a->b) -> a(类型为C f)。

如果你有

,也许不会那么混乱
C a b

但是因为对于newtype总是只有一个值构造函数(并且只有一个类型构造函数),所以将它们命名为相同是有意义的。

newtype CT a b = CV ((a->b) -> a) 是一个值构造函数,它接受一个函数,句号。该函数将具有签名CV,即其参数也是一个函数,但就(a->b) -> a而言,这并不重要。

实际上,CTdata声明使用newtype符号有点不对,因为它并不意味着左右两侧的内容“相同” - 不能,因为他们甚至不属于同一种语言。有一种替代语法可以更好地表达关系:

=

至于你试图构建的那个值

  

{-# LANGUAGE GADTs #-} data CT :: * -> * -> * where CV :: ((a->b) -> a) -> CT a b

这里你将“函数和参数”传递给let d1 = CV $ (\x->(2*x)) 3。您实际上做了什么 1 ,您将函数CV应用于值\x->2*x(可能还写了3)并将该数字传递给{{ 1}}。但正如我所说,6期望一个功能。然后发生的是,GHC试图将CV解释为一个函数,它给出了伪约束CV。这意味着:“如果6是数字类型,那么......”。当然,不是数字类型so the rest doesn't make sense either

1 这是因为Num ((a->b) -> a)具有最低优先级,即表达式(a->b)->a实际上被解析为$,或等效{{1} }}