类型瞥一眼
在 REPL 中,可以使用 :type 'a'
查看 'a'
的类型。
ghci> :type 'a'
'a' :: Char
可见 'a'
的类型即为 Char
。
ghci> :type "Hello"
"Hello" :: String
而 "Hello"
的类型即为 String
。
实质上,String
只是一个类型别名(type alias),它等同于
[Char]
,亦即 Char
列表。
ghci> :info String
type String :: *
type String = [Char]
-- Defined in ‘GHC.Base’
打印
可以使用 print
打印很多类型:
ghci> print 14
14
ghci> print 14.2
14.2
ghci> print 'a'
'a'
ghci> print "str"
"str"
而 putStrLn
和 putStr
只用于打印字符串:
ghci> putStrLn "114514"
114514
ghci> putStr "114514"
114514ghci>
显然的,前者在字符串末尾添加换行符。
拼接
-- concat.hs
myGreeting :: String
= "hello" ++ " world!"
myGreeting
hello :: String
= "hello"
hello
world :: String
= "world"
world
main :: IO ()
= do
main putStrLn myGreeting
putStrLn secondGreeting
where
= concat [hello, " ", world] secondGreeting
❯ ghc ./*.hs && ./concat
Linking concat ...
hello world!
hello world
可以使用 ::
标注类型,对于 top-level
声明,这是必要的。
拼接字符串可使用 ++
或 concat
。
作用域
-- Scope.hs
module Scope where
topLevelFunc :: Integer -> Integer
=
topLevelFunc x + woot + topLevelValue
x where woot :: Integer
= 10
woot
topLevelValue :: Integer
= 5 topLevelValue
woot
仅在 topLevelFunc
函数体中可以访问。而
topLevelFunc
和 topLevelValue
允许模块内,或导入该模块的作用域使用。where
和
let
都引入了本地绑定作用域。
拼接函数的类型
不妨查看 (++)
和 concat
的类型:
-- 接收两个列表,输出为一个列表
(++) :: [a] -> [a] -> [a]
-- 接收一组列表,输出为一个列表
concat :: [[a]] -> [a]
-- 当然如果使用 GHC 7.10 或更高, concat 的类型长这样:
concat :: Foldable t => t [a] -> [a]
-- 目前将 Foldable t => t [a] 看作 [[a]] 即可
这两个函数都能不同的类型,但同一函数中的类型 a
必须一致。这正是 Haskell 的重要特性——多态性(polymorphism)。
"hello" ++ " Chris" -- OK
"hello" ++ [1, 2, 3] -- Error
列表函数
因为 String
是特定类型的列表。因此,对于
String
也可以使用标准的列表函数。
例如,(:)
操作符,亦称 cons:
'c' : "hris" -- "chris"
'P' : "" -- "P
-- head
head "Snake" -- "S"
-- tail
tail "Snake" -- "nake"
-- take
take 0 "Snake" -- ""
take 1 "Snake" -- "S"
take 3 "Snake" -- "Sna"
take 6 "Snake" -- "Snake"
-- drop
drop 3 "Snake" -- "ke"
drop 114514 "Snake" -- ""
drop 1 "Snake" -- "nake"
-- (++)
"Pine" ++ "apple" -- "Pineapple"
-- !!
"Pineapple" !! 0 -- "P"
"Pineapple" !! 4 -- "a"
请注意,以上函数是不安全的(unsafe)。因为它们不考虑全部情况,并会抛出异常:
> head ""
ghci*** Exception: Prelude.head: empty list
> "0123" !! 5
ghci*** Exception: Prelude.!!: index too large
以上,即为基本的字符串处理。