Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 记忆旧数据_Loops_Haskell_State - Fatal编程技术网

Loops 记忆旧数据

Loops 记忆旧数据,loops,haskell,state,Loops,Haskell,State,记住你的第一次(在Haskell循环中) 我试着通过一些黑客问题来教自己一点哈斯克尔 我正在研究的问题涉及以坐标(x1,y1)和(x2,y2)和 确定由这些坐标绘制的多边形的周长 以下是我目前的代码: -- Calculate length of line given points x1,y2, x2,y2 calc_length:: Int -> Int -> Int -> Int -> Float calc_length x1 y1 x2 y2 = s

记住你的第一次(在Haskell循环中)

我试着通过一些黑客问题来教自己一点哈斯克尔

我正在研究的问题涉及以坐标(x1,y1)和(x2,y2)和 确定由这些坐标绘制的多边形的周长

以下是我目前的代码:

-- Calculate length of line given points x1,y2, x2,y2
calc_length:: Int -> Int -> Int -> Int -> Float 
calc_length x1 y1 x2 y2 =
       sqrt ( fromIntegral (height ^2 + width ^2)  )
       where height = abs( y2 - y1) 
             width  = abs( x2 - x1) 


main = do
        x <- readLn :: IO Double
        forM_ [1,2..(x / 2)] $ \lc -> do
           line1 <- getLine
           let wds1 = map (\str -> read str::Int) (words $ line1)
           line2 <- getLine
           let wds2 = map (\str -> read str::Int) (words $ line2)
           print ( wds1, wds2)
——计算给定点x1、y2、x2、y2的直线长度
计算长度::Int->Int->Int->Int->Int->Float
计算长度x1 y1 x2 y2=
sqrt(从整数(高度^2+宽度^2))
其中高度=绝对值(y2-y1)
宽度=绝对值(x2-x1)
main=do
x do
第1行读取str::Int(单词$line1)
第2行读取str::Int)(单词$line2)
打印(wds1、wds2)
我的问题是,我需要计算第一个坐标和最后一个坐标之间的距离,即记住输入的第一对数字(存储在第1行)。但在乘法迭代之后,第一对将丢失。我曾尝试使用全局变量存储getLine的第一次调用(几乎没有成功,即使成功了,我也不认为这会有帮助)

我觉得有一种更实用的方法我可以尝试,但就是不知道怎么做

我不是在寻找一个完整的编码解决方案,只是一种能为我指明更好方向的方法


有什么想法吗?

如果您需要以不同的方式对待第一次迭代,应该将其分开(如果我正确理解您的问题)。您可以使用辅助功能减少重复:

getNumLine :: IO [Int]
getNumLine = do
    line <- getLine
    return (map read (words line))

main = do
    x <- readLn :: IO Int   -- Double seemed wrong, use integer `div` below instead
    firstline <- getNumLine
    forM_ [2..x `div` 2] $ \lc -> do
        ...
getNumLine::IO[Int]
getNumLine=do

line您要求提供一种更实用的方式来思考这个问题,所以我将尝试提供这一点。你说你是Haskell的新手,所以如果这涉及到你还没有探索的东西,我提前道歉。请随时要求澄清其中的任何部分

首先,让我们对
calcLength
函数进行更多的分段。我们传递了两个点,所以与其传递四个参数,不如只传递两个

data Point a = Point a a

calcLength :: Floating a => Point a -> Point a -> a
calcLength (Point x1 y1) (Point x2 y2) = sqrt (height ^ 2 + width ^ 2)
    where height = abs (y2 - y1)
          width  = abs (x2 - x1)
现在,让我们编写一个读取单个点的函数。我们将从
main
调用它,而不是在
main
中分别读取两个数值

readPoint :: (Floating a, Read a) => IO (Point a)
readPoint = Point <$> readLn <*> readLn
newtype Polygon a = Polygon [Point a]

perimeter :: Floating a => Polygon a -> a
perimeter (Polygon xs) = sum . map (\(a, b) -> calcLength a b) $ loopedPairs xs
现在我们将编写一个周长函数。将尽可能多的“纯”非IO逻辑从IO工作中分离出来是很好的,因此我们希望将其从
main
中分离出来

readPoint :: (Floating a, Read a) => IO (Point a)
readPoint = Point <$> readLn <*> readLn
newtype Polygon a = Polygon [Point a]

perimeter :: Floating a => Polygon a -> a
perimeter (Polygon xs) = sum . map (\(a, b) -> calcLength a b) $ loopedPairs xs
我们取一个多边形,它实际上只是一个点列表,使用
loopedPairs
将所有点配对,然后计算每个点之间的长度,并将结果相加

考虑到这一点,
main
相当短

main :: IO ()
main = do
  n <- readLn :: IO Int
  points <- replicateM n (readPoint :: IO (Point Double))
  let result = perimeter (Polygon points)
  print result

我请你仔细分析一下,如果你有任何问题,请告诉我。函数式编程是一种很难掌握的思维方式,因为它与其他编程非常不同,但它是一套方便的技术,可以放在您的工具带中。

Everbody帮助后:我的最终解决方案:

import Control.Monad

data Point a = Point a a

newtype Polygon a = Polygon [Point a]

calcLength :: Floating a => Point a -> Point a -> a
calcLength (Point x1 y1) (Point x2 y2) = sqrt (height ^ 2 + width ^ 2)
    where height = abs (y2 - y1)
          width  = abs (x2 - x1)

readPoint :: (Floating a, Read a) => IO (Point a)
readPoint = Point <$> readLn <*> readLn

loopedPairs :: [a] -> [(a, a)]
loopedPairs [] = []
loopedPairs (x:xs) = go x xs
    where go x' (y:ys) =  (x', y) : go y ys
          go x' []     = [(x', x)]

perimeter :: Floating a => Polygon a -> a
perimeter (Polygon xs) = sum . map (\(a, b) -> calcLength a b) $ loopedPairs xs

main :: IO ()
main = do
  n <- readLn :: IO Int
  points <- replicateM n (readPoint :: IO (Point Double))
  let result = perimeter (Polygon points)
  print result
import Data.List
import Data.Foldable
import Data.Traversable
import Data.List.Split

          -- Calculate length of line given points x1,y2, x2,y2
          calc_length:: Int -> Int -> Int -> Int -> Float 
         calc_length x1 y1 x2 y2 =
               sqrt ( fromIntegral (height ^2 + width ^2)  )
               where height = abs( y2 - y1) 
                     width  = abs( x2 - x1)


        -- Calculate the distances between vertex points (except the last)
        getResults list = 
            sum [ calc_length (head f)  (last f) (head s)  (last s)   |  (f,s)  <-  (zip list (tail list)) ]  


       -- Calculate the last vertex distance between points
       headAndTail list =
           calc_length (z!!0) (z!!1) (z!!2) (z!!3)
           where z  = head list ++ last list 

        -- Prompt the user for co-ordinate pairs
        main = do
                x <- readLn :: IO Double
                result <- forM [1,2..x ] ( \lc -> do
                   line1 <- getLine
                   let wds1 = map (\str -> read str::Int) (words $ line1)
                   return wds1)

                print (  (getResults result) + (headAndTail result)   ) 
导入数据。列表
导入数据。可折叠
导入数据。可遍历
导入Data.List.Split
--计算给定点x1、y2、x2、y2的直线长度
计算长度::Int->Int->Int->Int->Int->Float
计算长度x1 y1 x2 y2=
sqrt(从整数(高度^2+宽度^2))
其中高度=绝对值(y2-y1)
宽度=绝对值(x2-x1)
--计算顶点之间的距离(最后一个顶点除外)
getResults列表=

求和[calc_length(head f)(last f)(head s)(last s)|(f,s)为什么不把所有坐标存储在一个列表中呢?只需将
表单
更改为
表单
,将
打印
更改为
返回
。嗨,梅尔波梅,好的,看起来我需要调查表单与表单的对比-我看到表单可以让我记住结果,而表单不需要。西尔维奥,感谢你花时间提供真正全面的回复。感谢你的努力。我是我相信我可以从你的代码中学到很多东西。我会花一些时间看看。