Haskell 언어 소스:

{-
    Filename: testHexView_02.hs

      Purpose: Show hexadecimal values of the given file.
 
    Compile: ghc testHexView_02.hs
    Execute: testHexView_02 [filename]
 
    Date: 2013. 8. 20.
-}

module Main where

import System.Directory
import System.Exit
import System.IO
import System.Environment
import Text.Printf
import Data.Bits
import Data.Char (ord)
import Data.Char (chr)
import Data.Array
import Data.List


printUsage :: IO()
printUsage = putStrLn "Usage: testHexView_02 [filename]"


strDupLoop :: String -> Integer -> String -> String
strDupLoop s n t = case n == 0 of
        True -> t
        _ -> strDupLoop s (n - 1) (t ++ s)

strDup :: String -> Integer -> String
strDup s n = strDupLoop s n ""

getHexStr :: String -> Integer -> Integer -> Integer -> String -> String
getHexStr s offset k cnt t = case k == cnt of
        True -> t
        _ -> getHexStr s offset (k + 1) cnt (t ++ c0 ++ (printf "%s" (toHex (ord (s !! (fromInteger (offset + k)))))))
                       where c0 = if k == 8 then "-" else " "

getDumStr :: String -> Integer -> Integer -> Integer -> String -> String
getDumStr s offset k cnt t = case k == cnt of
        True -> t
        _ -> getDumStr s offset (k + 1) cnt (t ++ (printf "%c" a))
                 where x = (s !! (fromInteger (offset + k)))
                       a = if (ord x) < (ord ' ') || (ord x) > 0x7F
                              then '.'
                              else x

printHexTable :: String -> Integer -> Integer -> IO()
printHexTable s offset size = case offset + 16 <= size of
    True -> do putStr $ printf "%s: " (toHex8 $ fromInteger offset)
               putStr (getHexStr s offset 0 16 "")
               putStrLn $ "  |" ++ (getDumStr s offset 0 16 "") ++ "|"
               printHexTable s (offset + 16) size
    _    -> do putStr $ printf "%s: " (toHex8 $ fromInteger offset)
               putStr (getHexStr s offset 0 (size - offset) "")
               putStr (strDup "   " (16 - size + offset))
               putStr $ "  |" ++ (getDumStr s offset 0 (size - offset) "")
               putStrLn $ (strDup " " (16 - size + offset)) ++ "|"
   

toHex :: Int -> [Char]
toHex n = printf "%c%c" sx1 sx2
          where x1 = shiftR (n .&. 0xF0) 4
                x2 = n .&. 0xF
                -- sx1 = show ((ord '0') + x1)
                -- sx2 = show ((ord 'A') + x2)
                sx1  = if x1 > 9
                       then
                            ((ord 'A') + (x1 - 10))
                       else
                            ((ord '0') + x1)
                sx2 = if x2 > 9
                      then
                            ((ord 'A') + (x2 - 10))
                      else
                            ((ord '0') + x2)


toHex8 :: Int -> [Char]
toHex8 n = printf "%c%c%c%c %c%c%c%c" sx1 sx2 sx3 sx4 sx5 sx6 sx7 sx8
          where x1 = shiftR (n .&. 0xF0000000) 28
                x2 = shiftR (n .&. 0xF000000) 24
                x3 = shiftR (n .&. 0xF00000) 20
                x4 = shiftR (n .&. 0xF0000) 16
                x5 = shiftR (n .&. 0xF000) 12
                x6 = shiftR (n .&. 0xF00) 8
                x7 = shiftR (n .&. 0xF0) 4
                x8 = n .&. 0xF
                sx1  = if x1 > 9
                       then
                            ((ord 'A') + (x1 - 10))
                       else
                            ((ord '0') + x1)
                sx2 = if x2 > 9
                      then
                            ((ord 'A') + (x2 - 10))
                      else
                            ((ord '0') + x2)
                sx3 = if x3 > 9
                      then
                            ((ord 'A') + (x3 - 10))
                      else
                            ((ord '0') + x3)
                sx4 = if x4 > 9
                      then
                            ((ord 'A') + (x4 - 10))
                      else
                            ((ord '0') + x4)
                sx5 = if x5 > 9
                      then
                            ((ord 'A') + (x5 - 10))
                      else
                            ((ord '0') + x5)
                sx6 = if x6 > 9
                      then
                            ((ord 'A') + (x6 - 10))
                      else
                            ((ord '0') + x6)
                sx7 = if x7 > 9
                      then
                            ((ord 'A') + (x7 - 10))
                      else
                            ((ord '0') + x7)
                sx8 = if x8 > 9
                      then
                            ((ord 'A') + (x8 - 10))
                      else
                            ((ord '0') + x8)


       
main :: IO ()
main = do
    args <- getArgs

    if (length args == 0)
       then do printUsage
               exitWith (ExitFailure 1)
       else do

    let fname = args !! 0

    dirExist <- doesDirectoryExist fname
    if dirExist
       then do putStrLn $ printf "%s is a directory." fname
               exitWith (ExitFailure 1)
       else do

    fileExist <- doesFileExist fname
    if not fileExist
       then do putStrLn $ printf "The file \"%s\" does not exist." fname
               exitWith (ExitFailure 1)
       else do
    inh <- openFile fname ReadMode
    fsize <- hFileSize inh
    inpStr <- hGetContents inh

    putStrLn $ printf "The size of the file \"%s\" is %d." fname fsize
    putStrLn ""

    printHexTable inpStr 0 fsize

    putStrLn ""
    putStrLn $ printf "Read %d bytes." fsize

    hClose inh

 

 

실행 예 1> testHexView_02 temp_1.bin
The size of the file "temp_1.bin" is 12.

0000 0000:  48 65 6C 6C 6F 20 74 68-65 72 65 0A              |Hello there.    |

Read 12 bytes.

실행 예 2> testHexView_02 myFile.ser
The size of the file "myFile.ser" is 130.

0000 0000:  AC ED 00 05 73 72 00 06-50 65 72 73 6F 6E 07 31  |....sr..Person.1|
0000 0010:  46 DB A5 1D 44 AB 02 00-03 49 00 03 61 67 65 4C  |F...D....I..ageL|
0000 0020:  00 09 66 69 72 73 74 4E-61 6D 65 74 00 12 4C 6A  |..firstNamet..Lj|
0000 0030:  61 76 61 2F 6C 61 6E 67-2F 53 74 72 69 6E 67 3B  |ava/lang/String;|
0000 0040:  4C 00 08 6C 61 73 74 4E-61 6D 65 71 00 7E 00 01  |L..lastNameq.~..|
0000 0050:  78 70 00 00 00 13 74 00-05 4A 61 6D 65 73 74 00  |xp....t..Jamest.|
0000 0060:  04 52 79 61 6E 73 71 00-7E 00 00 00 00 00 1E 74  |.Ryansq.~......t|
0000 0070:  00 07 4F 62 69 2D 77 61-6E 74 00 06 4B 65 6E 6F  |..Obi-want..Keno|
0000 0080:  62 69                                            |bi              |

Read 130 bytes.

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Haskell 언어에서는 asin 함수로 구현되어 있다.

또한 Haskell 언어에서는 쌍곡선함수 sinh, cosh 의 역함수들이 각각 asinh, acosh 라는 이름으로  이미 구현되어 있다. 그래서 비교를 위해 아래의 소스에 arcsinh, arccosh 라는 이름의 함수로 구현해 보았다.

영문 위키피디아의 GHC 설명: http://en.wikipedia.org/wiki/Glasgow_Haskell_Compiler

(참고. Haskell 언어는 대소 문자를 구분하며 타입에 엄격한 언어이다. ) 

아래의 소스는 Glasgow Haskell Compiler ghc 로 컴파일되는 소스이다.

 

{-
   Filename: testArcSine.hs
 
   Compile: ghc testArcSine.hs
   Execute: ./testArcSine
 
   Date: 2013. 1. 3.
   Copyright (c) pkim _AT_ scripts.pe.kr
-}

module Main where

import System.Environment
import Text.Printf

arcsinh :: (RealFloat a) => a -> a
arcsinh x = w where
                      w = log (x + sqrt (x*x + 1))

arccosh :: (RealFloat a) => a -> a
arccosh x = w where
                      w = log (x + sqrt (x*x - 1))


main :: IO ()       
main = do
    let x = -0.9 :: Double
    let y = asin x
   
    printf "y = asin(%f) = %.9f\n" x y
    printf "sin(y) = sin(%.9f) = %f\n" y (sin y)
    printf "\n"
   
    let x =1.1 :: Double
    let u = acosh x
    printf "u = acosh(%.1f) = %.10f\n" x u
    let v = asinh x
    printf "v = asinh(%.1f) = %.10f\n" x v
   
    printf "cosh(u) = cosh(%.10f) = %3.1g\n" u (cosh u)
    printf "sinh(v) = sinh(%.10f) = %3.1g\n" v (sinh v)
    printf "\n"

    printf "arccosh(%.1f) = %.10f\n" x (arccosh x)
    printf "arcsinh(%.1f) = %.10f\n" x (arcsinh x)


{-
Output:
y = asin(-0.9) = -1.119769515
sin(y) = sin(-1.119769515) = -0.9

u = acosh(1.1) = 0.4435682544
v = asinh(1.1) = 0.9503469298
cosh(u) = cosh(0.4435682544) = 1.1
sinh(v) = sinh(0.9503469298) = 1.1

arccosh(1.1) = 0.4435682544
arcsinh(1.1) = 0.9503469298
-}

 

 

Posted by Scripter
,

Haskell  언어로 행렬 곱셈하는 간단한 소스

(정수로 이루어진 행렬, 분수로 이루어진 행렬, 부동소수점수로 이루어진 행렬, 복소수로 이루어진 행렬 들릐 곱셈을 처리합니다.) 

 

-- Filename: testMatrixMultiplication.hs
--
-- 참조: http://rosettacode.org/wiki/Matrix_multiplication#Haskell

module Main where

import Data.Complex
import Data.Ratio
import Text.Printf
import Data.List 


-- 행렬 곱셉 함수
mmult :: Num a => [[a]] -> [[a]] -> [[a]] 
mmult a b = [ [ sum $ zipWith (*) ar bc | bc <- (transpose b) ] | ar <- a ]


-- 사용 예
main :: IO ()
main = do
    -- matrix of integers
    let test = [[1, 2], 
                  [3, 4]] `mmult` [[-3, -8, 3],
                                            [-2,  1, 4]]
    print test

    -- matrix of floats
    let test = [[1.0, 2.0], 
                    [3.0, 4.0]] `mmult` [[-3, -8, 3],
                                                   [-2,  1, 4]]
    print test

    -- matrix of fraction
    let test = [[(1 % 1),  (2 % 1)], 
                    [(3 % 1), (4 % 1)]] `mmult` [[-3, -8, 3],
                                                                [-2,  1, 4]]
    print test

    -- matrix of complex numbers
    let test = [[(1 :+ 1),  (2 :+ 1)], 
                    [(3 :+ 1), (4 :+ 1)]] `mmult` [[-3, -8, 3],
                                                                [-2,  1, 4]]
    print test

{-
실행: runhaskell testMatrixMultiplication.hs
출력:
-------------------------------------------
[[-7,-6,11],[-17,-20,25]]
[[-7.0,-6.0,11.0],[-17.0,-20.0,25.0]]
[[(-7) % 1,(-6) % 1,11 % 1],[(-17) % 1,(-20) % 1,25 % 1]]
[[(-7.0) :+ (-5.0),(-6.0) :+ (-7.0),11.0 :+ 7.0],[(-17.0) :+ (-5.0),(-20.0) :+ (-7.0),25.0 :+ 7.0]]
-}

 

 

 

Posted by Scripter
,

Haskell 언어로도 (Python 언어 처럼) 복소수 게산과 분수 게산을 쉽게 할 수 있습니다,.

(1) Haskell  언어에서 복소수를 사용하려면   import Data.Complex 구문이 있어야 합니다.
    복소수의 표현은 실수부 :+ 허수부 입니다.

(2) Haskell  언어에서 분수를 사용하려면   import Data.Ratio 구문이 있어야 합니다.
    분수의 표현은 분자 % 분모 입니다.

(3) C 언어의 printf 나 Python 언어의 print 처럼 포맷 출력을 하려면 import Text.Printf 구문이 있어야 합니다.

아래에서 진한 글자체로 된 부분만 입력하고 엔터키를 누르면 됩니다.
(ghci 는 Glasgow Haskell 의 인터프리터이고,. ghc는 Glasgow Haskell 의 컴파일러입니다.)


$ ghci
GHCi, version 7.0.4: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
-- 몫과 나머지 구하기
Prelude> div 5 3
1
Prelude> mod 5 3
2
Prelude> divMod 5 3
(1,2)
Prelude> 5 `div` 3
1
Prelude> 5 `mod` 3
2
Prelude> 5 `divMod` 3
(1,2)
-- 분수 생성과 계산
Prelude> import Data.Ratio
Prelude Data.Ratio> 5 % 3
5 % 3
Prelude Data.Ratio> 5 % 3 * 2
10 % 3
Prelude Data.Ratio> 5 % 3 + 2
11 % 3
Prelude Data.Ratio> 5 % 3 + 2 % 3
7 % 3
-- 복소수 생성과  계산
Prelude Data.Ratio> import Data.Complex
Prelude Data.Ratio Data.Complex> 2 :+ 3
2.0 :+ 3.0
Prelude Data.Ratio Data.Complex> sqrt 2 :+ 3
1.4142135623730951 :+ 3.0
Prelude Data.Ratio Data.Complex> sqrt (2 :+ 3)
1.6741492280355401 :+ 0.8959774761298381
Prelude Data.Ratio Data.Complex> 2 :+ 3 * 2
2.0 :+ 6.0
Prelude Data.Ratio Data.Complex> 2 :+ 3 - 2

<interactive>:1:1:
    Precedence parsing error
        cannot mix `:+' [infix 6] and `-' [infixl 6] in the same infix expressio
n
Prelude Data.Ratio Data.Complex> (2 :+ 3) - 2
0.0 :+ 3.0
Prelude Data.Ratio Data.Complex> (2 :+ 3) - 0:+2

<interactive>:1:1:
    Precedence parsing error
        cannot mix `-' [infixl 6] and `:+' [infix 6] in the same infix expressio
n
Prelude Data.Ratio Data.Complex> (2 :+ 3) - (0:+2)
2.0 :+ 1.0
Prelude Data.Ratio Data.Complex> (2 :+ 3) * 0:+2

<interactive>:1:13:
    No instance for (RealFloat (Complex a0))
      arising from a use of `:+'
    Possible fix:
      add an instance declaration for (RealFloat (Complex a0))
    In the expression: (2 :+ 3) * 0 :+ 2
    In an equation for `it': it = (2 :+ 3) * 0 :+ 2
Prelude Data.Ratio Data.Complex> (2 :+ 3) * (0:+2)
(-6.0) :+ 4.0
Prelude Data.Ratio Data.Complex> conjugate 2 :+ 3

<interactive>:1:13:
    No instance for (RealFloat (Complex a0))
      arising from a use of `:+'
    Possible fix:
      add an instance declaration for (RealFloat (Complex a0))
    In the expression: conjugate 2 :+ 3
    In an equation for `it': it = conjugate 2 :+ 3
Prelude Data.Ratio Data.Complex> conjugate (2 :+ 3)
2.0 :+ (-3.0)
relude Data.Ratio Data.Complex> 1 / 2 :+ 3
.5 :+ 3.0
Prelude Data.Ratio Data.Complex> 1 / (2 :+ 3)
.15384615384615385 :+ (-0.23076923076923078)
Prelude Data.Ratio Data.Complex>
Prelude Data.Ratio Data.Complex Text.Printf> let x = 2 :+ 5
Prelude Data.Ratio Data.Complex Text.Printf> printf "x = %f + %fj\n" (realPart x) (imagPart x)
x = 2.0 + 5.0j
-- 복소수 츨력하기
Prelude Data.Ratio Data.Complex Text.Printf> let printComplex a = print ((show (
realPart a)) ++ " + " ++ (show (imagPart a)) ++ "j")
Prelude Data.Ratio Data.Complex Text.Printf> printComplex x
"2.0 + 5.0j"
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (conjugate x)
"2.0 + -5.0j"
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (sin x)
"67.47891523845588 + -30.879431343588244j"
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (asin (sin x))
"1.1415926535897933 + -5.0j"
Prelude Data.Ratio Data.Complex Text.Printf> printComplex ((asin . sin) x)
"1.1415926535897933 + -5.0j"
-- 분수 츨력하기
Prelude Data.Ratio Data.Complex Text.Printf> let printFraction a = print ((show
(numerator a)) ++ "/" ++ (show (denominator a)))
Prelude Data.Ratio Data.Complex Text.Printf> let b = 2 % 3
Prelude Data.Ratio Data.Complex Text.Printf> printFraction b
"2/3"
Prelude Data.Ratio Data.Complex Text.Printf> printFraction (1/b)
"3/2"
Prelude Data.Ratio Data.Complex Text.Printf> printFraction ((1/b)*2)
"3/1"
-- (인용 부호 없이) 분수 츨력하기
Prelude Data.Ratio Data.Complex Text.Printf> let printFraction a = printf "%d/%d
\n" (numerator a) (denominator a)
Prelude Data.Ratio Data.Complex Text.Printf> printFraction b
2/3
Prelude Data.Ratio Data.Complex Text.Printf> printFraction (1/b)
3/2
Prelude Data.Ratio Data.Complex Text.Printf> printFraction ((1/b)*2)
3/1
-- (인용 부호 없이) 복소수 츨력하기
Prelude Data.Ratio Data.Complex Text.Printf> let printComplex a = printf "%f + %
fj\n" (realPart a) (imagPart a)
Prelude Data.Ratio Data.Complex Text.Printf> printComplex x
2.0 + 5.0j
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (conjugate x)
2.0 + -5.0j
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (sin x)
67.47891523845588 + -30.879431343588244j
Prelude Data.Ratio Data.Complex Text.Printf> printComplex (asin (sin x))
1.1415926535897933 + -5.0j
Prelude Data.Ratio Data.Complex Text.Printf> printComplex ((asin . sin) x)
1.1415926535897933 + -5.0j
Prelude Data.Ratio Data.Complex Text.Printf> :q
Leaving GHCi.

 

 

※ 다음은 위에 입력한 내용들을 모아서 만든 Haskell 소스 파일입니다.

{-#
      Filename: complexAndFraction.hs
          Testing the expressions and calculations of complex numbers and fractions in Haskell.

     Compile: ghc complexAndFraction.hs
     Execute: ./complexAndFraction

     Or
 
     Execute: runhaskell complexAndFraction.hs
#-}

module Main where

import Data.Complex
import Data.Ratio
import Text.Printf


{-#  복소수 출력하는 함수 #-}
printC :: (RealFloat a, Show a) => Complex a -> IO ()
printC a = print ((show (realPart a)) ++ " + " ++ (show (imagPart a)) ++ "j")

{-#  분수 출력하는 함수 #-}
printF :: (Integral a, Num a, Eq a, Show a) => Ratio a -> IO ()
printF a = print ((show(numerator a)) ++ "/" ++ (show (denominator a)))

{-#  (인용 부호 없이) 복소수 출력하는 함수 #-}
-- printfFraction :: (PrintfArg a, Show a, Eq a, Integral a) => Ratio a -> IO ()
printFraction :: (Show a, Integral a) => Ratio a -> IO ()
printFraction a = printf "%s/%s\n" (show (numerator a)) (show (denominator a))

{-#  (인용 부호 없이) 분수 출력하는 함수 #-}
-- printfComplex :: (Num a, RealFloat a, Show a, PrintfArg a) => Complex a -> IO ()
printComplex :: (Show a, RealFloat a) => Complex a -> IO ()
printComplex a = printf "%s + %sj\n" (show (realPart a)) (show (imagPart a))


main :: IO ()       
main = do
    -- 몫과 나머지 구하기
    print (div 5 3)
    print (mod 5 3)
    print (divMod 5 3)
    print (5 `div` 3)
    print (5 `mod` 3)
    print (5 `divMod` 3)

    -- 분수 생성과 계산
    print (5 % 3)
    print (5 % 3 * 2)
    print (5 % 3 + 2)
    print (5 % 3 + 2 % 3)

    -- 복소수 생성과  계산
    print (2 :+ 3)
    print (sqrt 2 :+ 3)
    print (sqrt (2 :+ 3))
    print (2 :+ 3 * 2)
    print ((2 :+ 3) - 2)
    print ((2 :+ 3) - (0:+2))
    print ((2 :+ 3) * (0:+2))
    print (conjugate (2 :+ 3))
    print (1 / 2 :+ 3)
    print (1 / (2 :+ 3))

    let x = 2 :+ 5
    printf "x = %s + %sj\n" (show (realPart x)) (show (imagPart x))

    -- 복소수 츨력하기 --
    printC x
    printC (conjugate x)
    printC (sin x)
    printC (asin (sin x))
    printC ((asin . sin) x)

    -- 분수 츨력하기
    let b = 2 % 3
    printF b
    printF (1/b)
    printF ((1/b)*2)

    -- (인용 부호 없이) 분수 츨력하기
    printFraction b
    printFraction (1/b)
    printFraction ((1/b)*(2%1))

    -- (인용 부호 없이) 복소수 츨력하기
    printComplex x
    printComplex (conjugate x)
    printComplex (sin x)
    printComplex (asin (sin x))
    printComplex ((asin . sin) x)
{-
------
Output:
------
1
2
(1,2)
1
2
(1,2)
5 % 3
10 % 3
11 % 3
7 % 3
2.0 :+ 3.0
1.4142135623730951 :+ 3.0
1.6741492280355401 :+ 0.8959774761298381
2.0 :+ 6.0
0.0 :+ 3.0
2.0 :+ 1.0
(-6.0) :+ 4.0
2.0 :+ (-3.0)
0.5 :+ 3.0
0.15384615384615385 :+ (-0.23076923076923078)
x = 2.0 + 5.0j
"2.0 + 5.0j"
"2.0 + -5.0j"
"67.47891523845588 + -30.879431343588244j"
"1.1415926535897933 + -5.0j"
"1.1415926535897933 + -5.0j"
"2/3"
"3/2"
"3/1"
2/3
3/2
3/1
2.0 + 5.0j
2.0 + -5.0j
67.47891523845588 + -30.879431343588244j
1.1415926535897933 + -5.0j
1.1415926535897933 + -5.0j
-}

 

 

 

Posted by Scripter
,

 

GHC 의 runhaskell 명령으로 소스 파일을 직접 실행해도 되고,

ghc 명령으로 컴파일하여 생성된 실행파일을 실행해도 된다.

 

-- Filename: solveQuadratic.hs
--    Solve a quadratic equation.
--
--   Compile: ghc solveQuadratic.hs
--   Execute: solveQuadratic 1 3 2
--
--   Or
--
--   Execute: runhaskell solveQuadratic.hs 1 3 2

{-
Compile: ghc solveQuadratic.hs
Execute & Result: solveQuadratic 1 0 4
     Quadratic Equation: 1.0x^2 + 0.0x + 4.0 = 0
     Discriminant D = -16.0
     x1 = 2.0j
     x2 = -2.0j

Or

Execute & Result: runhaskell solveQuadratic.hs 1 0 4
     Quadratic Equation: 1.0x^2 + 0.0x + 4.0 = 0
     Discriminant D = -16.0
     x1 = 2.0j
     x2 = -2.0j
-}

module Main where

import System.Environment
import Data.Complex
import Text.Printf

printUsing :: IO ()
printUsing = do
    putStrLn "Using: runhugs solveQuadratic.hs coeff2  coeff1  coeff0"
    putStrLn "Or solveQuadratic coeff2  coeff1  coeff0"
    putStrLn "Find the roots pf a quadratic equations."


printSolution :: [Char] -> Double -> Double -> IO()
printSolution msg x y = do
           if not (y == 0) && not (x == 0)
           then
               printf "%s%f + %fj\n" msg x y
           else  if not (y == 0) && (x == 0)
           then
               printf "%s%fj\n" msg y
           else
               printf "%s%f\n" msg x

printEquation :: Double -> Double -> Double -> IO()
printEquation a b c =    printf "Quadratic Equation: %fx^2 + %fx + %f = 0\n" a b c

solveEquation :: (RealFloat a) => a -> a -> a -> [Complex a]
solveEquation a b c = x1:x2:[] where
                        za = (a :+ 0)
                        zb = (b :+ 0)
                        zc = (c :+ 0)
                        discr = zb*zb - 4*za*zc
                        x1 = (-zb + sqrt (discr))/(2*za)
                        x2 = (-zb - sqrt (discr))/(2*za)

main :: IO ()       
main = do
    args <- getArgs

    if not ((length args) == 3)
        then printUsing
    else do
    let a1:b1:c1:ts = args
    let a = read a1 :: Double
    let b = read b1 :: Double
    let c = read c1 :: Double
    let d = b*b - 4.0*a*c

    printEquation a b c
    printf "Discriminant D = %g\n" d
    let sols = solveEquation a b c
    let x1:x2:x3 = sols

    printSolution "x1 = " (realPart x1) (imagPart x1)
    printSolution "x2 = " (realPart x2) (imagPart x2)

 

 

Posted by Scripter
,


* 꼬리 재귀호출과 패턴 매칭을 이용하여 구현한 팩토리얼과 피보나치 수열 계산

{-
    Filename: fact.hs
         Rapid factorial and fibonacci seq implementations
         by pattern matching and tail recursive call

    Compile: ghc fact.hs
    Execute: main

    Date: 2010/07/20
    Author: phkim  pkim (AT) scripts.pe.kr
-}

module Main where

  factorial :: Integer -> Integer
  factorial n =  recfact 1 n

  recfact :: Integer -> Integer -> Integer
  recfact acc k = case k of
        0 -> acc
        k-> recfact (acc*k) (k - 1)

  fib :: Integer -> Integer
  fib n = fibGen 0 1 n

  fibGen :: Integer -> Integer -> Integer -> Integer
  fibGen a b n = case n of
        0 -> a
        n -> fibGen b (a + b) (n - 1)

  main :: IO ()
  main = do
        print ("Factorial(30000) has " ++ show (length (show (factorial 30000))) ++ " digits")
        print ("Fibonacci(200000) has " ++ show (length (show (fib 200000))) ++ " digits")

{-
    Expected result:
    "Factorial(30000) has 121288 digits"
    "Fibonacci(200000) has 41798 digits"
-}



크리에이티브 커먼즈 라이선스
Creative Commons License

 

Posted by Scripter
,

Haskell 언어로 숫자 맞추기 게임을 작성해 보았다.
순수한 함수형 언어로는 반복문을 어떻게 구현하는 가를 보여주는 한 예제로 보면 된다.  

대화형 방식으로 사용자의 입력 스트링을 받아서 정수로 변환하여 비교 처리하는 과정도 눈여겨 볼 만한 부분이다. (18째 줄 이하)



소스 파일명: guessNumber01.hs

  1. {-# 
  2.    Filename: guessNumber01.hs
  3.    Purpose:  Interactive game guessing a given number.
  4.                  if .... else ... then ...
  5.    Execute: runhugs guessNumber01.hs
  6.          Or
  7.             runhaskell guessNumber01.hs
  8. #-}
  9. module Main where
  10. main :: IO ()
  11. main = doGuessing 123
  12. doGuessing :: (Ord a, Read a) => a -> IO ()
  13. doGuessing num = do
  14.   putStrLn "Enter your guess: "
  15.   guess <- getLine
  16.   case compare (read guess) num of
  17.     EQ -> do putStrLn "You win!"
  18.              return()
  19.     LT -> do print "Too low!";
  20.              doGuessing num
  21.     GT -> do print "Too high!";
  22.              doGuessing num



WinHugs의 runhugs.exe를 이용하여 스크립트 소스파일 guessNumber01.hs을 실행해 보았다.

실행> runhugs guessNumber01.hs
Enter your guess:
111
"Too low!"
Enter your guess:
222
"Too high!"
Enter your guess:
123
You win!



GHC의 runhakell을 이용하여 스크립트 소스파일 guessNumber01.hs을 실행해 보았다.
(주석문 {-# .... #-} 이 GHC에서는 인식되지 않음을 알 수 있다.)

실행> runhaskell guessNumber01.hs

guessNumber01.hs:1:0: Unrecognised pragma

guessNumber01.hs:1:0: Unrecognised pragma
Enter your guess:
111
"Too low!"
Enter your guess:
222
"Too high!"
Enter your guess:
123
You win!



WinHugs의 대화형 인터프리터 hugs.exe를 이용하여 스크립트 소스파일 guessNumber01.hs를 실행해 보았다. 마지막에 :quit는 인터프리터를 종료하는 명령이다.


실행> hugs
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Bugs: http://hackage.haskell.org/trac/hugs
||   || Version: 20051031       _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Type :? for help
Hugs> :load guessNumber01.hs
Main> main
Enter your guess:
111
"Too low!"
Enter your guess:
222
"Too high!"
Enter your guess:
123
You win!

Main> :quit
[Leaving Hugs]





WinHugs의 GUI 대화형 인터프리터 winhugs.exe를 이용하여 스크립트 소스파일 Gugudan.hs을 실행해 보았다. :cd는 change directory 명령이고 :load는 소스파일 탑재(load) 명령이다.
소스파일이 탑재되고 나면 프롬프트가 Main> 으로 바뀐다. 이는 소스파일에 main 함수가 작성되어 있기 때문이다.


    <wingugs.exe를 이용하여 guessNumber01.hs를 실행시킨 장면>






Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.


Posted by Scripter
,

 명령프롬프트> hugs
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Bugs: http://hackage.haskell.org/trac/hugs
||   || Version: 20051031       _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Type :? for help
Hugs> "2" + "5"
ERROR - Cannot infer instance
*** Instance   : Num [Char]
*** Expression : "2" + "5"

Hugs> read "2" + read "5"        -- read 는 스트링을 Int 타입으로 형변환하는 함수이다.
7
Hugs> read "2.1" + read "5"        -- read 는 스트링을 Double 타입으로 형변환하지 못한다.

Program error: Prelude.read: no parse

Hugs> read "2.1" :: Double + read "5"       -- Double 타입이라고 형을 명시적으로 지정하면 변환해준다. 그러나 구문에러이다.
ERROR - Syntax error in input (unexpected token)
Hugs> (read "2.1") :: Double + read "5"    -- 여전히 구문 에러이다.
ERROR - Syntax error in input (unexpected token)
Hugs> ((read "2.1") :: Double) + read "5"   -- 구문 에러가 해결되었다.
7.1
Hugs> (read "2.1" :: Double) + read "5"      -- 속에 있는 소괄호는 없어도 된다.
7.1
Hugs> :quit 



 Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

Posted by Scripter
,

소스 파일명: testIf.py

  1. {-#
  2.    Filename: testIf.hs
  3.    Purpose:  Example using the conditional control structure syntax
  4.                  if .... else ... then ...
  5.    Execute: runhugs testIf.hs [number]
  6.          Or
  7.             runhaskell testIf.hs [number]
  8. #-}
  9. module Main where
  10. import System.Environment
  11. -- 사용법을 보여주는 함수
  12. printUsing :: IO ()
  13. printUsing = do
  14.     putStrLn "Using: runhugs testIf.hs [number]"
  15.     putStrLn "This determines whether the number is positive or not."
  16. main :: IO ()
  17. main = do
  18.     args <- getArgs
  19.     -- 명령행 인자의 개수가 1이 아니면 사용법을 보여준다.
  20.     if not ((length args) == 1)
  21.         then printUsing
  22.         else do
  23.             let val = toDouble (args !! 0)
  24.             if val > 0.0
  25.                then putStrLn ((show val) ++ " is a positive number.")
  26.                else if val < 0.0
  27.                    then putStrLn ((show val) ++ " is a negative number.")
  28.                    else putStrLn ((show val) ++ " is zero.")
  29. toDouble :: [Char] -> Double
  30. toDouble x = (read x) :: Double

 


위의 소스에서
            if not ((length args) == 1)
로 된 부부은
            if not ((length args) == 1)
로 해도 된다. 즉, Haskell 언어의 /=  비교연산자는 C 언어의 != 비교연산자와 같은 의미이다.

실행> runhugs testIf.hs
Using: runhugs testIf.hs [number]
This determines whether the number is positive or not.

실행> runhugs testIf.hs 6.25
6.25 is a positive number.

실행> runhugs testIf.hs -6.25
-6.25 is a negative number.



* GHC의 ghc 명령으로 컴파일한 후 실행하기

컴파일> ghc --make testIf.hs

testIf.hs:1:0: Unrecognised pragma
[1 of 1] Compiling Main             ( testIf.hs, testIf.o )

testIf.hs:1:0: Unrecognised pragma
Linking testIf.exe ...

실행> testIf
Using: runhugs testIf.hs [number]
This determines whether the number is positive or not.

실행> testIf 6.25
6.25 is a positive number.

실행> testIf -6.25
-6.25 is a negative number.




Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.


Posted by Scripter
,

*파일명: sumSquares.hs
module Main where
import System.Environment

main :: IO ()
main = do
    args <- getArgs
    let arr = toDouble args
    print (arr)
    putStr "Total is "
    print (sumIt arr)

toDouble :: [[Char]] -> [Double]
toDouble xs = [(read x)**2 :: Double | x <- xs]

sumIt :: [Double] -> Double
sumIt [] = 0
sumIt [x] = x
sumIt (x:xs) = x + sumIt xs





*파일명: sumSquares2.hs
module Main where
import System.Environment

main :: IO ()
main = do
    args <- getArgs
    let arr = toDouble args
    print (arr)
    putStr "Total is "
    print (sumIt arr)

toDouble :: [[Char]] -> [Double]
toDouble xs = [square ((read x) :: Double) | x <- xs]

sumIt :: [Double] -> Double
sumIt [] = 0
sumIt [x] = x
sumIt (x:xs) = x + sumIt xs

square :: Double -> Double
square x = x*x


 

 

* WInHugs에서 runhugs로 실행하기
프롬프트> runhugs sumSquares.hs 1 2 3 4 5
[1.0,4.0,9.0,16.0,25.0]
Total is 55.0

프롬프트> runhugs sumSquares2.hs 1 2 3 4 5
[1.0,4.0,9.0,16.0,25.0]
Total is 55.0



* GHC의 runhaskell로 실행하기
프롬프트> runhaskell sumSquares2.hs 1 2 3 4 5
[1.0,4.0,9.0,16.0,25.0]
Total is 55.0

프롬프트> runhaskell sumSquares.hs 1 2 3 4 5
[1.0,4.0,9.0,16.0,25.0]
Total is 55.0



* GHC의 ghcl로 컴파일한 후 실행하기 (--make 옵션은 실행파일을 만들라는 의미의 옵션이다.)
프롬프트> ghc --make sumSquares.hs

프롬프트>sumSquares
[]
Total is 0.0

프롬프트> sumSquares 1 2 3 4 5
[1.0,4.0,9.0,16.0,25.0]
Total is 55.0


Posted by Scripter
,