我对Haskell非常新,并试图学习这头野兽.这是一个简单的函数,可以将时间(以秒为单位)转换为[天,小时,分钟,秒].我已经用签名和类型挣扎了半天,但我仍然遇到类型错误.看起来我已经尝试过各种签名组合 - 没有运气.能否请你帮忙.
secToTime :: Integer -> [Integer]第一个并且得到了一堆类型错误,这些错误足以让我迷惑不解.是显示结果列表的正确方法:main = do print secToTime或main = do map (\x -> putStrLn . show) secToTime?
secToTime secs = [d,h,m,s]
where s = secs `rem` 60
m = truncate(secs / 60) `rem` 60
h = truncate(secs / 3600) `rem` 24
d = truncate(secs / 86400)
Run Code Online (Sandbox Code Playgroud)谢谢
问题在于你正在混合rem,它与Integrals一起使用并且/与Fractionals一起使用.并且易于修复将用于div代替/.这也意味着truncate不需要因为div表示整数除法.
基本上,Haskell将类似整数的类型与其他类型区分开来.类型类中的任何Integral类型都像一个整数 - 这些包括Int,Integer以及大量更专业的类型Word.对于您的特定代码,您希望将所有数字视为整数,因此您应该使用类似的类型的函数Integral a => a -> a -> a,div而不是/.
另请注意:由于您的时间表示总是有四个字段,因此不应使用列表.您可以改为使用元组(d,h,m,s)或创建自己的类型:
data Time = Time Integer Integer Integer Integer deriving (Show, Eq)
Run Code Online (Sandbox Code Playgroud)
这个deriving (Show, Eq)位只是给你show和免费==的Time类型.
所以,把所有这些放在一起,我们得到这个功能:
secToTime secs = Time d h m s
where s = secs `rem` 60
m = secs `div` 60 `rem` 60
h = secs `div` 3600 `rem` 24
d = secs `div` 86400
Run Code Online (Sandbox Code Playgroud)
所以现在自然的问题是,这有什么类型的签名?它实际上非常简单:
secToTime :: Integer -> Time
Run Code Online (Sandbox Code Playgroud)
请注意这是如何使返回数据代表的非常明显!
由于Time派生Show,我们可以使用print它.所以我们可以:
main = print $ secToTime 12345
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为在内部print只调用show后输出结果.由于Time是一个实例Show,它有一个show定义的函数,因此可以使用print.
运行此程序将打印:
Time 0 3 25 45
Run Code Online (Sandbox Code Playgroud)
但是,这不是一个理想的结果!它打印的格式很尴尬.相反,让我们首先摆脱派生Show:
data Time = Time Integer Integer Integer Integer deriving (Eq)
Run Code Online (Sandbox Code Playgroud)
并写我们自己的.有趣!
instance Show Time where
show (Time d h m s) = show d ++ " days " ++
show h ++ " hours " ++
show m ++ " minutes " ++
show s ++ " seconds"
Run Code Online (Sandbox Code Playgroud)
现在,当我们运行时main,我们得到这个输出:
0 days 3 hours 25 minutes 45 seconds
Run Code Online (Sandbox Code Playgroud)
它好多了.基本上,我们所做的就是通过指定实例和定义函数告诉Haskell Times应该如何看作Strings .Showshow
鉴于您有一个Time类型,您可以使用模式匹配从中提取值:
timeToSec (Time d h m s) = d * 86400 + h * 3600 + m * 60 + s
Run Code Online (Sandbox Code Playgroud)
该模式(Time d h m s)需要你的Time价值和解构它放回它包含四个整数,命名它们d,h,m和s.这使您可以Time通过获取实际数字来编写可以在s上运行的任意函数.