Make-haskell函数接受自己作为参数



我目前正在学习haskell,试图使函数successor要么接受Num并返回其后继函数(4 == successor 3(,要么接受自身并返回双后继函数(5 == (successor successor) 3(。

使successor函数成为其类Successor的一种类型的正确方法是什么?

幼稚Successor

class Successor a where
successor :: a -> a

instance Successor Int where
successor n
| (==) 1 n = 2
| otherwise = 1 + successor (n - 1)

测试代码

n :: Int
n = 3
m = successor (successor n)
main = do
print m -- print 5

所需行为

n :: Int
n = 3
m = (successor successor) n
main = do
print m -- print 5

这对我来说似乎是个糟糕的主意——为什么要编写一个同时处理数字和函数的函数?

无论如何,你可以实现你的要求(但可能不是你真正想要的(如下:

{-# LANGUAGE FlexibleInstances #-}
module Main where
class Successor a where
successor :: a -> a
instance Successor Int where
successor n
| (==) 1 n = 2
| otherwise = 1 + successor (n - 1)
instance Successor (Int -> Int) where
successor f = f . f
n' :: Int
n' = 3
m1 :: Int
m1 = successor (successor n')
m2 :: Int
m2 = (successor successor) n'
main :: IO ()
main = do
print m1 -- print 5
print m2 -- print 5

定义successor f = f . f适用于这种特定情况,其中f = successor,但在其他情况下可能不会产生预期的输出。

我们可以使用successor f = successor . f这样的变体。也许这在总体上更有用,但对我来说仍然是个坏主意

我同意chi的观点,认为这可能是个坏主意,但如果你要有这样一个类型类,那么我会尽可能通用:

class Successor a where
scs :: a -> a
instance Successor Int where
scs = succ  -- don't reinvent the wheel
instance Successor a => Successor (c -> a) where
scs f = scs . f

然后

ghci> scs scs (scs (scs scs)) ((scs scs) scs) scs (scs scs) 0 :: Int
11

相关内容

最新更新