문제

문화적, 지적 풍요 로움을 위해, 나는 약간의 Haskell을 배우기로 결정했습니다. 나는 읽고 있었다 휴즈의 "기능 프로그래밍이 중요한 이유" 그리고 코드를 True Haskell으로 변환하려고합니다. 아래에 내 시도 중 일부를 첨부했습니다 (논문의 수치 부분에 대해서는 알파 베타 알고리즘이 더욱 흥미롭지 만 게임 평가자도 처음부터 작성해야합니다!).

이 시점에서 그것은 Haskell Syntax에서 다른 어떤 것보다 더 많은 운동이었습니다. 나는 이미 번역과 같은 간단한 일을 해냈습니다 repeat 원주민 Haskell로 iterate, 많은 괄호를 사용하여 작곡 (프로세스에서 더 많은 포인트가없는) 등을 사용한 몇 가지 기능을 번역합니다.

그러나 내 코드는 확실히 작동하며 충분히 "Haskell-ish"인지 궁금합니다. 거기에있는 전문가가 나에게 힌트를 줄 수 있습니까?

-- 4.1 Newton-Raphson square roots
next n x = (x + n/x)/2.0

-- -- this is "iterate::(a->a)->a->[a]"
-- repeat f a  = a : iterate f (f a)

within eps (a:b:rest) = 
  if abs(a-b) <= eps 
    then b
    else within eps (b:rest)

sqroot a0 eps n = within eps (iterate (next n) a0)

relative eps (a:b:rest) = 
  if abs(a-b) <= eps*abs(b)
    then b
    else relative eps (b:rest)

relativesqrt a0 eps n = relative eps (iterate (next n) a0)

-- 4.2 numerical differentiation

easydiff f x h = (f (x+h) - f x) / h

differentiate h0 f x = map (easydiff f x) (iterate (/2) h0)

-- diff1a h0 eps f x = within eps (differentiate h0 f x)
diff1 h0 eps f = within eps . differentiate h0 f 

elimerror n (a:b:rest) = (b*(2**n)-a)/(2**n-1) : elimerror n (b:rest)

-- need fromIntegral to make a non-integer out of the Int which comes out of round
order (a:b:c:rest) =  fromIntegral (round (logBase 2 ((a-c)/(b-c)-1)))

improve s = elimerror (order s) s 

--diff2a h0 eps f x = within eps (improve (differentiate h0 f x))
diff2 h0 eps f = within eps . improve . differentiate h0 f 

--super s = map second (iterate improve s) -- how can we make this point-free?
super :: (RealFrac t, Floating t) => [t] -> [t] 
           -- w/o this it wants to be [double]->[double]
super = map second . iterate improve

-- second (a:b:rest) = b
second = head . tail

diff3 h0 eps f = within eps . super . differentiate h0 f

-- 4.3 integration

easyintegrate f a b = (f a + f b)*(b-a)/2

-- addpair becomes (uncurry (+))

integrate f a b = integ f a b (f a) (f b) 

integ f a b fa fb = 
  (fa+fb)*(b-a)/2 : map (uncurry (+)) (zip (integ f a m fa fm) (integ f m b fm fb))
  where m = (a+b)/2 
        fm = f m 

-- test: following should be about pi
approxpi eps = within eps (improve (integrate (\x -> 4/(1+x*x)) 0 1))
superpi eps = within eps (super (integrate (\x -> 4/(1+x*x)) 0 1))

-- is there any way to keep track of the number of iterations? state monad, but seems like a lot of work...\

올바른 솔루션이 없습니다

다른 팁

4.1 뉴턴-라프 슨 스퀘어 뿌리

이 두 줄

sqroot a0 eps n = within eps (iterate (next n) a0)
relativesqrt a0 eps n = relative eps (iterate (next n) a0)

거의 동일하므로 한 걸음 더 나아갈 수 있습니다.

sqroot method a0 eps n = method eps (iterate (next n) a0)
relativesqrt = sqroot relative
withinsqrt   = sqroot within

4.2 수치 차별화

나는 요점을 보지 못한다 h0 에 대한 논쟁으로 differentiate 그것은 단지 시작점이므로 기능합니다. 0 제한 시퀀스. (마찬가지로 사실이 아닙니다 a0 시작점이 중요한 Newton-Rhapson 사례에서).

이 한계가 0에 접근하는 비율에 대해 추상화하는 것이 똑같이 적절하다고 생각합니다.

differentiate rate f x = map (easydiff f x) (iterate rate 1)

물론 하나는 둘 다 할 수 있습니다.

differentiate rate h0 f x = map (easydiff f x) (iterate rate h0)

어쨌든 그것은 꽤 임의의 결정입니다.

4.2 통합

당신이 사용할 수있는

zipWith (+) (integ f a m fa fm) (integ f m b fm fb)

대신에

map (uncurry (+)) (zip (integ f a m fa fm) (integ f m b fm fb))

더 읽기 쉬운 것 같아요.

을 위한 within 그리고 relative 나는 보호 표기법을 사용합니다.

within eps (a:b:rest)
  | abs(a-b)<=eps = b
  | otherwise = within eps (b:rest)

을 위한 second, 당신은 쓸 수 있습니다 !! 1. 특히 마지막 것은 개인적인 취향이라고 생각합니다.

또한 유형 서명을 제공해야합니다.

편집하다: 난독 화에 빠지면 시도해보십시오.

within :: (Ord a, Num a) => a -> [a] -> a
within eps l@(_:xs) = snd. head . filter ((<= eps) . fst) $ zip zs xs
   where
    zs = zipWith (\ a b -> abs (a-b)) l xs

(유형 확인, 테스트되지 않은 유형 - 필터를 오른쪽으로 가져 오는지 또는 부정 해야하는지 알 수 없습니다.)

Roger Costello는 John Hughes의 두 부분 요약을 작성했습니다. 종이 원래 Miranda 코드를 Haskell로 번역합니다. 여기에 있습니다 1 부 그리고 두 번째 부분 그의 글의.

따라서 이것은 스트레이트 아 크로스 번역 (즉, 코드를 가능한 한 비슷하게 보이도록 노력하십시오) 또는 임베디드 (예 : 예제를 이해하기 어려운 예제를 만들지 않고 가능한 한 많은 관용적 조정을 만듭니다. ) 하나?

이 "프로젝트"가 여전히 진행되고 있다고 가정하면 ......

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top