GHCi, version 8.6.3: http://www.haskell.org/ghc/ :? for help [1 of 1] Compiling Main ( helloworld.hs, interpreted ) Ok, one module loaded. *Main> foo "hello, world" *Main>
-- 接受一个整型参数,返回一个新函数。这个新函数接受一个整型,返回一个整型 product' :: Int -> (Int -> Int) product' x y = x * y timesThree = product' 3 nine = timesThree 3 nine' = (product' 3) 3
-- 接受一个参数,该参数是“接受一个整型,返回一个整型”的函数,然后返回一个整型 some_func :: (Int -> Int) -> Int some_func f = f 42 -- *Main> some_func (* 2) -- 84
dataTupleOf a = MakeTupleOf a a -- MakeTupleOf :: a -> a -> TupleOf a -- MakeTupleOf False True :: TupleOf Bool -- MakeTupleOf 1 2 :: Num a => TupleOf a -- MakeTupleOf plus1 plus2 :: Num a => TupleOf (a -> a)
-- 你可以使用函数的模式匹配来提取数据结构中的成员 printNameAndAge :: NameAndAge -> String printNameAndAge (MakeNameAndAge name age) = "I'm " ++ name ++ " and I'm " ++ (show age) ++ " years old."
-- 你也可以使用模式匹配来判断是哪一个构造函数 printIntOrBool :: IntOrBool -> String printIntOrBool (MakeInt n) = "Wow, an integer: " ++ (show n) printIntOrBool (MakeBool b) = "Wow, a boolean: " ++ (show b)
-- 你甚至可以进行递归类型定义 。当然,你需要一个终止条件。 dataListOf a = EmptyList | AppendList (ListOfa) a
-- 相关操作也需要使用递归函数来完成 contains :: (Eq a) => ListOf a -> a -> Bool containsEmptyList _ = False contains (AppendList list x') x = if x == x' thenTrueelse contains list x
*Main> :info Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool {-# MINIMAL (==) | (/=) #-} -- Defined in ‘GHC.Classes’ instance [safe] Eq a => Eq (ListOf a) -- Defined at [omitted] [... omitted ...]
*Main> :info Monad classApplicative m => Monad (m :: * -> *) where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b return :: a -> m a fail :: String -> m a
简化一下
1 2 3
classMonad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a
当我们说Maybe是一个Monad的时候,一方面指 Maybe 属于 Monad 这个类型类instance Monad Maybe where ...。另一方面指Maybe(数据结构),(>>=)::Maybe a -> (a -> Maybe b) -> Maybe b (函数),return::a -> Maybe a (函数)这三者构成了一个满足某些条件的数学结构,这些条件被称为Monad Laws。事实上,Haskell编译器不会检查 Monad Laws 是否满足,你可以胡乱写一些数据结构和函数,然后将其塞入 Monad 这个类型类中。换句话说,Haskell中的Monad就是一个接口,任何实现接口的数据类型都可以称其为Monad。
回到Maybe上,现在你想把这两个会失败的函数连接在一起
1 2 3 4 5 6 7
func3 :: Float -> MaybeBool -- 错误示范,类型不匹配 -- func3 = func2.func1 -- 正确示范 func3 n = case (func1 n) of Nothing -> Nothing Just n' -> func2 n'
看上去不错,我们需要一种操作,能把任意两个可失败的函数连在一起,这样以后再碰到这种情况直接复用就行了。如果第一个函数类型是a->Maybe b,第二个函数类型是b->Maybe c,那么复合函数的类型应该是a->Maybe c
1 2 3 4 5 6 7
composite :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c) composite f g = \x -> case g x of Nothing -> Nothing Just y -> f y