Haskell数学类型系统的乐趣

时间:2011-04-04 19:22:43

标签: math haskell

我有以下Haskell代码

import Data.Int
import System.Environment

type Coord = (Int16, Int16)

distributePointsOverCircle :: Int16 -> Int16 -> [Coord]
distributePointsOverCircle points radius =
  [ (xOf point, yOf point) | point <- [1..points] ]
  where
    xOf x = abstract cos x
    yOf x = abstract sin x

    abstract :: RealFrac a => ( a -> a ) -> Int16 -> Int16
    abstract f x   = (radius *) . truncate . f . fromIntegral $ (angleIncrement * x) * truncate (pi / 180)
    angleIncrement = div 360 points

main = do
  [a,b] <- getArgs
  print $ distributePointsOverCircle (read a) (read b)

无论我传递给distributePointsOverCircle,它总是给我一个Coords的列表,因为我给出了每个Coord的第一个元素是半径而第二个元素为零的点。显然,这不是点的均匀分布。

我在这里做错了什么?是否有一些类型系统欺骗捏造我的数字?我试图用伪造的伪代码编写的函数是。

distributePointsOverCircle( numberOfPoints, radius )
  angleIncrement = 360 / numberOfPoints
  points         = []

  for i in 0 to (numberOfPoints -1)
    p = Point()
    p.x = (radius * cos((angleIncrement * i) * (PI / 180)))
    p.y = (radius * sin((angleIncrement * i) * (PI / 180)))

    points[i] = p

  return points

2 个答案:

答案 0 :(得分:5)

它为您提供了一个( r ,0)列表,因为truncate (pi / 180) == 0。删除truncate,代码应该可以正常工作。

abstract f x = (radius *) . truncate . f $ fromIntegral (angleIncrement * x) * (pi / 180)

答案 1 :(得分:2)

以下是我最终的结果:

import Data.Int
import System.Environment

type Coord = (Int16, Int16)

distributePointsOverCircle :: Int16 -> Int16 -> [Coord]
distributePointsOverCircle points radius =
  [ (xOf point, yOf point) | point <- [1..points] ]
  where
    xOf x = abstract cos x
    yOf x = abstract sin x
    iRadius = fromIntegral radius
    angleIncrement = div 360 points
    abstract f x = round . (iRadius *) . f $ angle * (pi / 180)
      where 
        angle = fromIntegral $ angleIncrement * x

main = do
  [a,b] <- getArgs
  print $ distributePointsOverCircle (read a) (read b)

正如已经提到的,问题是您在乘法之前使用了truncate,以便除其他事项truncate (pi / 180) == 0之外。我还认为你的主要功能有一些错误。