与Haskell中的(高阶)函数进行模式匹配

alb*_*laz 5 haskell functional-programming function pattern-matching

我正在尝试使用在线书"学习你的哈斯克尔"学习一些Haskell,我对高阶函数有疑问.

我看了一些例子,我想做一些更高级的功能,但我不知道为什么我总是阅读以下异常:

***例外:euler13.hs:(11,0) - (15,39):函数中的非详尽模式适用

我定义的功能就是这个:

apply :: (Num b, Ord b) => (a -> a) -> b -> [a] -> [a]
apply f n [] = []
apply f n [x]
    | n <= 1    = map f [x]
    | otherwise = apply f (n-1) (map f [x])
Run Code Online (Sandbox Code Playgroud)

我想将一个名为'f'的具体函数'n'应用于列表'[x]'.我试图使这个函数具有多态性,因此param的类型是'a'.但我也想使用数字和列表,所以我直接使用一个列表(如果我只想使用该函数的数字,那么显然会是[数字])

请问有人帮帮我吗?我喜欢这种语言,但是当你学习它时有点困难,因为它与Java或c有很大不同(例如)

谢谢!

ken*_*ytm 14

删除[]周围的x.否则,第二个模式只能匹配仅包含1个元素的列表.

apply f n x
    | n <= 1    = map f x
    | otherwise = apply f (n-1) (map f x)
Run Code Online (Sandbox Code Playgroud)

  • 当我们在它时:将其重命名为`xs`,这是"任何事物列表"的更常见的名称. (8认同)

app*_*ive 11

这与其他人所说的没有什么不同,但也许这一点应该付出代价?列表有两个基本的"构造函数",因此在从列表定义函数时需要考虑两个基本情况:表单的参数 [](:).后者,(:)可以加入任何东西与这种事情的列表,因此1[] - 1:[][1].或者它可以加入1那种类似的东西:1:(1:[])1:[1],[1,1]因为特殊的语法让我们写.

如果您自己定义了列表,那么更明显的是会出现什么问题,写道:

data List a = Nil | Cons a (List a) deriving (Show, Eq, Ord)
Run Code Online (Sandbox Code Playgroud)

对于像这样的东西,使用[]x:xs只是swank糖.同样地,特殊的String糖让我们写"abc"而不是['a','b','c'],这比我更好'a':'b':'c':[].(使用上面的定义,我们必须编写Cons 'a' (Cons 'b' (Cons 'c' Nil)))一个对于短字符串来说有点多的东西! - 尽管它也会说明为什么人们应该更喜欢ByteStringText字符串的表示用于许多目的.)使用更详细的列表定义,我们需要添加我们自己map(或更确切地说fmap),所以我们可以说

instance Functor List where 
   fmap f Nil = Nil
   fmap f (Cons first rest) = Cons (f first) (fmap f rest)
Run Code Online (Sandbox Code Playgroud)

请注意,在fmap为这种情况定义时,我必须考虑我的List类型的两种类型的构造函数,Nil并且Cons first rest(或者Cons x xs经常编写它).

或许你还没有达到FunctorLYAH 中关于类型类的一般性讨论- 在这种情况下,只要考虑你可以将自己定义map

listMap f Nil = Nil
listMap f (Cons first rest) = Cons (f first) (listMap f rest)
Run Code Online (Sandbox Code Playgroud)

在任何情况下,鉴于这种对列表类型的重写,您的实际函数定义将是:

apply :: (Num b, Ord b) => (a -> a) -> b -> List a -> List a
apply f n Nil = Nil
apply f n (Cons first Nil)
    | n <= 1    = fmap f (Cons first Nil)  -- or listMap f (Cons first Nil)
    | otherwise = apply f (n-1) (fmap f (Cons first Nil))
Run Code Online (Sandbox Code Playgroud)

您涉及的案例包括:

apply f n Nil 
apply f n (Cons first Nil)
Run Code Online (Sandbox Code Playgroud)

Cons first Nil和你一样- first : []或者就像你写的一样.但这意味着你没有涵盖所有案例,你的定义是"非详尽的".如果它有多个成员,您还没有说明如何申请和列表.如果列表具有形式或而不是(您的第一行)或(您的第二行),该怎么办?[first][x]fnCons x (Cons y Nil)Cons x (Cons y (Cons z Nil))NilCons x Nil

解决方案正如其他人所说,或使用我们的desugared列表类型:

apply :: (Num b, Ord b) => (a -> a) -> b -> List a -> List a
apply f n Nil = Nil
apply f n (Cons first rest)
    | n <= 1    = fmap f (Cons first rest)
    | otherwise = apply f (n-1) (fmap f (Cons first rest))
Run Code Online (Sandbox Code Playgroud)

这里的"变量" rest涵盖了所有列表Nil.因此我们得到:

*Main> apply (+1) 3 Nil
Nil
*Main> apply (+1) 3 (Cons 3 Nil)
Cons 6 Nil
Run Code Online (Sandbox Code Playgroud)

像你一样,但也:

*Main> apply (+1) 3 (Cons 0 (Cons 1 (Cons 2 Nil)))
Cons 3 (Cons 4 (Cons 5 Nil))
Run Code Online (Sandbox Code Playgroud)


900*_*000 5

您可以定义apply两种情况:n和空列表以及n和一个元素的列表.当列表包含多个元素时会发生什么?这是缺失的模式.