Haskell математическая система типов веселья - PullRequest
3 голосов
/ 04 апреля 2011

У меня есть следующий код на 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)

Независимо от того, что я передаю в disttePointsOverCircle, он последовательно выдает мне список сколь угодно большого числа координат, поскольку я даю точки, где первый элемент каждой координаты является радиусом и вторымэлемент равен нулю.Очевидно, это не равномерное распределение очков.

Что я здесь не так делаю?Есть ли какая-то хитрость системы типов, которая обманывает мои цифры?Функция, которую я пытаюсь создать, написанная в императивном псевдокоде, будет иметь следующий вид:

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 ]

5 голосов
/ 04 апреля 2011

Это дает вам список ( r , 0), потому что truncate (pi / 180) == 0. Удалите truncate, и код должен работать нормально.

abstract f x = (radius *) . truncate . f $ fromIntegral (angleIncrement * x) * (pi / 180)
2 голосов
/ 05 апреля 2011

Вот что я закончил:

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 (pi / 180) == 0.Я также думаю, что у вас были некоторые ошибки в вашей основной функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...