2010-12-03 4 views
6

누군가 내가 하스켈에서 올바른 코드를 얻는 방법을 "얻지 못하고있다"고 말했습니다.하나의 함수로 haskell의 함수 목록을 캡슐화하십시오.

mev = matrixExpValues 5 4 3 
cs = canonicalSt 4 3 

cs_t1 = map (foldl (++) "") (map (map show) cs) 
cs_t2 = map (++ ":") cs_t1 
mev_t1 = intXxsToStringXxs mev 
mev_t2 = map (map (++ "\t")) mev_t1 
mev_t3 = map (foldl (++) "") mev_t2 
res1 = zipWith (++) (map (++ "\t") cs_t2) mev_t3 
res2 = map (++ "\n") res1 
final_result = foldl (++) "" res2 

와 : 내 모든 하스켈 코드를 느끼게하지만, 간단한 기능 (적어도 자바 또는 C와 같은 "표준"언어 내 OOP 코드 ++에 비해) 정말 못생긴대로 그 사람이 완전히 오른쪽해야합니다 mev과의 cs : 내가 가진 때까지

*Main> mev 
[[2,-2,-2,-6],[4,2,0,-2],[2,2,4,4],[6,4,2,2],[6,4,2,6]] 
*Main> cs 
[[0,0,4],[0,1,3],[0,2,2],[1,1,2]] 

(! 그 값이 손 입력 된, 나는 임의의 mevcs에 대한 작업이 필요합니다) 내가 처음에 2 차원 매트릭스를 가지고있는 나는 작업의 순서를 적용합니다 원하는 결과.

이 기능은 작동하지만, 이제는이 모든 로직을 단일 기능으로 캡슐화하고자합니다 (matrix_transf라고 부름). 현재 코드는 무엇 matrixExpValuescanonicalSt 반환에 묶여, 나는

matrix_transf mev cs = 
    ...all those transformations 
    ...until I get to final_result 

비판의 모든 종류 (나는 내가 개선 할 필요!) 나는 좋은 하스켈 코더 것으로 예상 환영처럼 뭔가를하고 싶습니다 아마도 완전히 다른 방식으로이 문제에 접근하고 그것이 내가 알고 자하는 것입니다!

답변

8

첫 번째로 저는 여러분에게 보여줄 것이 최적이 아니라고 말하고 싶습니다 (예를 들어 KennyTM의 코드는 훨씬 좋아 보입니다).하지만 여러분이 코드를 바꾸면 어떻게 보이는지 보여 드리고 싶습니다. intXxsToStringXxs 가능하면 정의 인라인 동안

  • map f (map g xs) ==>map (f.g) xs

: map (map show) 연속적 규칙을 적용한다.꽤 Afer 즉

  • foldl (++) "" ==>concat
  • concat (map f xs) ==>concatMap f xs
  • concatMap (++ "\n") ==>unlines

: 또한, 더 잘 보이게하기 위해, 나는이 규칙을 적용했습니다 다시 작성하면 다음과 같이 표시됩니다.

cs_t3 = map ((++ ":\t") . concatMap show) cs 
mev_t3 = map (concatMap ((++"\t") . show)) mev 
final_result = unlines (zipWith (++) cs_t3 mev_t3) 

나는 그것이 훨씬 더 보이지 않는다 알고있다, 그러나 당신이이 같은 matrix_transf 쓸 수 있는지를 알아 내기 위해 지금 너무 오래 걸리지 않을 겁니다 :

matrix_transf mev cs = unlines (zipWith (++) (starts cs) (endings mev)) 

starts = map ((++ ":\t") . (concatMap show)) 
endings = map (concatMap ((++"\t") . show))  

또는이 같은 :

matrix_transf mev cs = unlines . zipWith (++) starts $ endings 
    where starts = map ((++ ":\t") . (concatMap show)) cs 
      endings = map (concatMap ((++"\t") . show)) mev 
13
  1. 라이브러리를 확인하십시오. 예를 들어, foldl (++) "" xconcat로 대체 될 수 있으며, ++ "\t" 물건 등 등

  2. 당신은 지역의 '변수'를 정의하는 wherelet을 사용할 수, Data.List.intercalate하여 수행 할 수 있습니다.

는 그때

import Data.List 

matrix_transf mev cs = 
    unlines $ zipWith processEntry mev cs 
    where processEntry mev_entry cs_entry = 
      concatMap show cs_entry ++ ":\t" ++ 
      intercalate "\t" (map show mev_entry) 
*Main> putStrLn $ matrix_transf [[2,-2,-2,-6],[4,2,0,-2],[2,2,4,4],[6,4,2,2],[6,4,2,6]] [[0,0,4],[0,1,3],[0,2,2],[1,1,2]] 
004: 2 -2 -2 -6 
013: 4 2 0 -2 
022: 2 2 4 4 
112: 6 4 2 2 

(이 함수 다릅니다 작성합니다 형태

004: 2 -2 -2 -6 
013: 4 2 0 -2 
... 

에이 목록을 변환 할 가정 후행 탭은 존재하지 않습니다.)

0

이전 솔루션이 각 필드 다음에 탭과 다르게 콜론 뒤에 탭을 처리하는 방법을 재밌었습니다. 테이블을 덤프 할 때 대개 각 필드는 탭으로 시작하는 대신 탭으로 시작하는 것으로 처리합니다. @KennyTM의 버전이 더 읽기 쉽다고 생각합니다.

matrix_transf mev cs = 
    unlines $ zipWith processEntry mev cs 
    where processEntry mev_entry cs_entry = 
      concatMap show cs_entry ++ ":" ++ 
      concapMap (("\t" ++) . show) mev_entry 
관련 문제