Haskell - 为给定签名实现一个函数

时间:2013-05-22 00:26:05

标签: haskell null char signature

我必须使用以下签名实现一个示例函数:

[[([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)

几个问题:

  1. 为什么第二个参数返回t而不是(a -> b -> Char)
  2. 我通过' '获取Char,但它确实有效,但我希望传递一个像''这样的空char-arg,但它不起作用。
  3. 为什么我在结果签名中得到t3和t4而不是t1和t2?
  4. 提前致谢

    编辑: 我的下一次尝试:

    funcD1 [[([' '],x,y)]] (uFunc0D x y = ' ' where _ = x y) = ([' '],  uFunc1D)
        where
            uFunc1D y x  = ' '
    

1 个答案:

答案 0 :(得分:4)

  1. uFunc0D未被使用(您使用具有相同名称的函数隐藏where子句中的参数)
  2. ' '表示字符文字,必须包含一个字符。你可能会想到字符串,在这种情况下""是空字符串。
  3. uFunc1D的参数与输入参数xy完全无关,因此可以自由选择不同的类型。
  4. 编辑:

    你必须使用表达式中的参数(等号的右侧)来影响返回类型。您在where子句中的声明介绍了uFunc0DuFunc1DuFunc0D的声明在函数的参数(左侧)中隐藏了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

    arg1arg2的位置是模式。进入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(作为第二个参数绑定)从右手边)。

    函数的参数位置总是模式,模式可能看起来像表达式,但它们不是!某些代码是表达式还是模式,取决于它与其他所有内容的关系,而不是它的外观。