如何在haskell中获取数字的所有子数

时间:2015-06-30 12:42:27

标签: haskell

我想从特定的一方获得一个数字的所有子编号。

在数字1234的情况下,左侧的子编号为:

1, 12, 123, 1234

我用以下方式实现了它:

tail . inits $ show 1234

这样我就可以[[Char]]格式获得所有子编号。

["1","12","123","1234"]

我尝试将它们转换为Integer,使用以下行。

map read . tail . inits $ show 1234

但是我收到以下错误

[*** Exception: Prelude.read: no parse

我做错了什么?

4 个答案:

答案 0 :(得分:3)

因为解释器不知道你想要什么类型

这将有效:

λ> map read . tail . inits $ show 1234 :: [Int]
[1,12,123,1234]

当然你也可以添加一个类型签名(最有可能在你的代码文件中):

subnums :: Int -> [Int]
subnums = map read . tail . inits . show

在ghci:

λ> subnums 1234
[1,12,123,1234]

如果没有show / read

,可以做一个很好的练习
subnumbers :: Int -> [Int]
subnumbers 0 = []
subnumbers n =
  n : subnumbers (n `div` 10)

你能解决这里的订单问题吗?

答案 1 :(得分:3)

一个好方法是使用展开。虽然折叠(在其他语言中称为 reduce 累积聚合)可以处理数字列表(或其他类型的值)计算单个结果值,展开以单个值开始,并根据给定函数将其扩展为值列表。让我们检查一下展开函数的类型:

Data.List.unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

我们看到unfoldr采用函数(b -> Maybe (a, b)和起始b。结果是[a]。如果函数的计算结果为Just (a, b),则a将附加到结果中,展开将使用新的b进行递归。如果函数的计算结果为Nothing,则展开完成。

你展开的功能是:

f :: Integral b => b -> Maybe (b, b)
f x = if x > 0 
  then Just (x, x `div` 10)  -- append x to result; continue with x/10
  else Nothing               -- x = 0; we're done

现在我们可以在没有任何showread hackery的情况下解决您的问题:

λ> let f = (\x -> if x > 0 then Just (x, x `div` 10) else Nothing)
λ> reverse $ unfoldr f 1234
[1,12,123,1234]

答案 2 :(得分:2)

作为Carsten suggests,您需要指出您想要的类型。这是因为read在结果类型中是多态的。在编译器知道你想要什么类型之前,它不知道要使用什么解析器!显式类型注释通常是要走的路,但有时您可能会考虑函数

asTypeOf :: a -> a -> a
asTypeOf x _ = x

如何在这里使用

我在这里看到两种使用asTypeOf的明显方法:

λ> asTypeOf (map read . tail . inits $ show 1234) ([0] :: [Int])
[1,12,123,1234]

λ> map (asTypeOf read length) . tail . inits $ show 1234
[1,12,123,1234]

第一个看起来几乎没有好转,第二个可能对初学者来说有点棘手 - 但它确实有效;)

为什么呢?由于length的类型为[a] -> Int,因此结果类型将固定为Int

λ> :t (`asTypeOf` length)
(`asTypeOf` length) :: ([a] -> Int) -> [a] -> Int

这正是我们read

所需要的

请注意length做什么并不重要 - 只有它的类型很重要 - 任何其他具有兼容签名的功能都会起作用(尽管我现在只能使用length

例如:

wantInt :: [a] -> Int
wantInt = undefined

λ> map (asTypeOf read wantInt) . tail . inits $ show 1234
[1,12,123,1234]

答案 3 :(得分:1)

工作清单理解解决方案:

subNums :: Int -> [Int]
subNums num = [read x | let str = show num, let size = length str, n <- [1 .. size], let x = take n str]

λ> subNums 1234
[1,12,123,1234]