我必须使用以下签名实现一个示例函数:
[[([Char], a, b)]] -> (a -> b -> Char) -> ([Char], b -> a -> Char)
所以我尝试这样:
funcD [[([' '],x,y)]] uFunc0D = ([' '], uFunc1D)
where
uFunc0D x y = ' '
uFunc1D y x = ' '
但是,当我用
调用它的类型时:t funcD
它返回
funcD :: [[([Char], t1, t2)]] -> t -> ([Char], t3 -> t4 -> Char)
几个问题:
t
而不是(a -> b -> Char)
?' '
获取Char,但它确实有效,但我希望传递一个像''
这样的空char-arg,但它不起作用。提前致谢
编辑: 我的下一次尝试:
funcD1 [[([' '],x,y)]] (uFunc0D x y = ' ' where _ = x y) = ([' '], uFunc1D)
where
uFunc1D y x = ' '
答案 0 :(得分:4)
uFunc0D
未被使用(您使用具有相同名称的函数隐藏where
子句中的参数)' '
表示字符文字,必须包含一个字符。你可能会想到字符串,在这种情况下""
是空字符串。uFunc1D
的参数与输入参数x
和y
完全无关,因此可以自由选择不同的类型。编辑:
你必须使用表达式中的参数(等号的右侧)来影响返回类型。您在where
子句中的声明介绍了uFunc0D
和uFunc1D
。 uFunc0D
的声明在函数的参数(左侧)中隐藏了uFunc0D
绑定,因此即使你要提到uFunc0D
rhs,它将是你在where子句中声明的那个,而不是参数。
编辑2:
这是一个例子,比如你想要一个函数f :: (a -> b) -> a -> Char
天真的尝试可能是:f f1 x = ' '
,但这将是f :: a -> b -> Char
类型。因为f1
应该是一个函数的事实是未知的(实际上,你可以传递其他东西作为f1
),并且它接受与第二个参数相同类型的事实也不得而知。
相反,如果您执行:f f1 x = ' ' where _ = f1 x
,则类型将为f :: (a -> b) -> a -> Char
。在这种情况下,编译器知道f1必须至少使用一个参数(因为您将它应用于参数),并且参数必须具有第二个参数的类型(因为您将它应用于第二个参数)。 / p>
编辑3:
关于haskell语法的一句话。
函数声明如下所示:f arg1 arg2 = expr
arg1
和arg2
的位置是模式。进入expr
的是表达式。
如果您看到类似
的内容f x = y
where y = x + 1
在where
子句之前的是表达式,接下来是表达式中可见的声明。 where
令牌之前的换行符不重要,上面与f x = y where y = x + 1
相同。
什么是模式?模式允许您将值分解为多个部分,并将部分绑定到名称。
x
是一种模式,例如id x = x
。这意味着x
绑定到id
的第一个参数。右侧的x
不是一个模式,而是一个表达式,一个值为x
的表达式,由模式绑定在左侧。
(a, b)
是另一种模式,如fst (a, b) = a
中所示。此模式表明输入类型应为2元组,第一个元素绑定到a
,第二个元素绑定到b
。
在mkPair a b = (a, b)
中,(a, b)
是表达式,而不是模式。它是一个具有2元组值的表达式,其第一个元素是a
(绑定为左侧的第一个参数),第二个值b
(作为第二个参数绑定)从右手边)。
函数的参数位置总是模式,模式可能看起来像表达式,但它们不是!某些代码是表达式还是模式,取决于它与其他所有内容的关系,而不是它的外观。