你如何在Haskell中指定任何类型?

时间:2013-11-28 04:07:39

标签: haskell

我必须将列表分成两半,导致列表的前半部分和列表的后半部分(half1,half2)的元组。当这个列表的长度是奇数时,我想让half1包含比half2更多的元素。如果给出一个空列表,我想要一个([],[])元组。但是,以下代码给出了一个错误。

 halve :: [a] -> ([a],[a])
 halve [] = ([],[])
 halve xs =
    if (((length(xs) `mod` 2)==1))
    then(take (ceiling(toRational(length(xs) `div` 2))) xs, drop(ceiling(toRational(length(xs) `div` 2))) xs)
    else ((take (floor(toRational(length(xs) `div` 2))) xs, drop (floor(toRational(length(xs) `div` 2))) xs))
 main = do
 putStrLn(show (halve [1,2,3])) 
 putStrLn(show (halve [])) gives me an error

我认为对于putStrLn(show(halve []))的错误,解释器不知道数组是由什么构成的,但我怎么能这样做以便类型无关紧要以便该行给出我([],[])。

3 个答案:

答案 0 :(得分:2)

问题是[]是多态的吗?它的类型是[] :: [a]。这与我们使用Show的事实相结合意味着我们的类型为Show a => [a]

现在Haskell不知道我们想要哪个a,而且选择很重要!如果aChar,则打印("", ""),如果a不是,则可能会打印([], [])。所以我们必须决定我们想要使用什么类型。

一个简单的诀窍是[] :: String只是""。所以

putStrLn (show (halve ""))

由于print是相同的行为

print (halve "")

如果我们不想使用Char,那么我们就可以写

print (halve ([] :: [SomeType]))

答案 1 :(得分:2)

你不能这样做。您必须指定列表的内容。这是静态类型的工作方式,ghc必须在编译时知道。所以你必须有这样的东西。

main = do                                                                           
    print (halve [1,2,3])                                                           
    print (halve ([] :: [Int]))

另外,我清理了你的减半功能。

halve :: [a] -> ([a],[a])                                                           
halve [] = ([],[])                                                                  
halve xs                                                                            
    | odd l         = splitAt ((l `div` 2) + 1) xs                                  
    | otherwise     = splitAt (l `div` 2) xs                                        
  where l = length xs 

答案 2 :(得分:0)

顺便说一句,你的halve函数编写得有些糟糕。你可以使这个功能更短,如下:

halve :: [a] -> ([a], [a])
halve xs = (take n xs, drop n xs) 
  where n = ceiling . (/2) . toRational . length $ xs

这取决于take n [] == drop n [] == []

此外,在Haskell中,函数调用f(a,b) == f a b不需要括号,而g(f(x))可以写成g . f $ x

最后,正如其他人所提到的,你需要指定[]的类型,编译器可以找到相应的show实例。

(一个巧妙的技巧是print = putStrLn . show

main = do
  print $ halve [1,2,3]
  print $ halve ([] :: [Integer])