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)
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)))一个对于短字符串来说有点多的东西! - 尽管它也会说明为什么人们应该更喜欢ByteString和Text字符串的表示用于许多目的.)使用更详细的列表定义,我们需要添加我们自己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)