سؤال

لدي رمز C التالي:

#include <sys/times.h>
#include <time.h>


float etime_( float *tarray )
{   struct tms buf;

    times( &buf );

    tarray[0] = 1.0 * buf.tms_utime / CLOCKS_PER_SEC;
    tarray[1] = 1.0 * buf.tms_stime / CLOCKS_PER_SEC;

    return tarray[0] + tarray[1];
}

محاولة ميناء هذا الكود Fortran إلى Haskell:

  PROGRAM Test
    IMPLICIT NONE

    REAL t, ta(2), etime

    INTEGER i
    DOUBLE PRECISION x

    do i = 1, 10000
       x = sin( cos( i * 1.0 d0 ) )
       print *, x 
    enddo

    ta(1) = 0.0d0
    ta(2) = 0.0d0

    t = etime( ta )       

    PRINT *, 'user time:    ', ta(1)
    PRINT *, 'system time:  ', ta(2)
    PRINT *, 'process time: ', t

  END

كيف يمكنني تحديد الصفيف و! أو !!! للحصول على رمز أدناه للعمل؟

module Main where

import GHC.Ptr
import GHC.Prim
import System.IO.Unsafe
import Control.Monad

foreign import ccall etime_ :: Ptr Double → IO Double
etime = etime_

main :: IO Int
main = do
  mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
  ta ← array 2
  t ← etime ta
  putStrLn $ "user time:    " ++ show (ta !!! 0)
  putStrLn $ "system time:  " ++ show (ta !!! 1)
  putStrLn $ "process time: " ++ show t
  return 0

array :: Int → IO (Ptr a)
array size = undefined

(!) :: Ptr a → Int → IO a
(!) = undefined

(!!!) :: Ptr a → Int → a
(!!!) = undefined
هل كانت مفيدة؟

المحلول

أقترح هذا:

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.Marshal.Array (allocaArray, peekArray)
import Foreign.Ptr (Ptr)

foreign import ccall etime_ :: Ptr Float -> IO Float

main :: IO ()
main = do
  mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
  allocaArray 2 $ \ta -> do
    ptime <- etime_ ta
    [utime, stime] <- peekArray 2 ta
    putStrLn $ "user time:    " ++ show utime
    putStrLn $ "system time:  " ++ show stime
    putStrLn $ "process time: " ++ show ptime

ولكن للإجابة على أسئلتك المحددة:

array :: Storable a => Int -> IO (Ptr a)
array = mallocArray

(!) :: Storable a => Ptr a -> Int -> IO a
(!) = peekElemOff

(!!!) :: Storable a => Ptr a -> Int -> a
(!!!) ptr = unsafePerformIO . peekElemOff ptr

أقترح استخدام Hoogle للعثور على الوظائف التي تحتاجها.

نصائح أخرى

إرجاع المبلغ، وقت المستخدم، ووقت النظام كقوام. لاحظ أن الادئة تأخذ مؤشرا لتعويمها، وليس مضاعفة، لذا فإن جعل أنواعك توافق على:

{-# LANGUAGE ForeignFunctionInterface #-}

module Main where

import Foreign (Ptr)
import Foreign.Marshal.Array (allocaArray,peekArray)
import Control.Monad (mapM_)

foreign import ccall etime_ :: Ptr Float -> IO Float

etime :: IO (Float, Float, Float)
etime = do
  allocaArray 2 $ \ta -> do
    t <- etime_ ta
    [user,sys] <- peekArray 2 ta
    return (t,user,sys)

main :: IO Int
main = do
  mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
  (t,user,sys) <- etime
  putStrLn $ "user time:    " ++ show user
  putStrLn $ "system time:  " ++ show sys
  putStrLn $ "process time: " ++ show t
  return 0

بالنظر إلى وحدة Haskell إضافية التالية:

module AllocSymbols (

  (↑≣), -- mallocArray
  (≣⊠), -- free

  (≣→), -- peekElemOff
  (≣←), -- pokeElemOff

  (⥱), -- peekElemOff unsafe

  (⥅), -- advancePtr

) where

import GHC.Ptr
import System.IO.Unsafe
import Foreign.Storable
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array

(↑≣) :: Storable a ⇒ Int → IO (Ptr a)
(↑≣) = mallocArray

(⥱) :: Storable a ⇒ Ptr a → Int → a
a ⥱ i = unsafePerformIO $ peekElemOff a i

(≣→) :: Storable a ⇒ Ptr a → Int → IO a
(≣→) = peekElemOff

(≣←) :: Storable a ⇒ Ptr a → Int → a → IO ()
(≣←) = pokeElemOff

(⥅) :: Storable a ⇒ Ptr a → Int → Ptr a
(⥅) = advancePtr

(≣⊠) :: Ptr a → IO ()
(≣⊠) = Foreign.Marshal.Alloc.free

والآن يمكننا مرفذ هذه القطعة من رمز FORTRAN:

  PROGRAM Test
    IMPLICIT NONE

    REAL t, ta(2), etime

    INTEGER i
    DOUBLE PRECISION x

    do i = 1, 10000
       x = sin( cos( i * 1.0 d0 ) )
       print *, x 
    enddo

    ta(1) = 0.0d0
    ta(2) = 0.0d0

    t = etime( ta )       

    PRINT *, 'user time:    ', ta(1)
    PRINT *, 'system time:  ', ta(2)
    PRINT *, 'process time: ', t

  END

كلمة للكلمة إلى haskell:

module Main where

import GHC.Ptr
import AllocSymbols
import Control.Monad

foreign import ccall etime_ :: Ptr Float → IO Float

main :: IO ()
main = do
  mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1 .. 10000 :: Int]

  ta ← (2 ↑≣) -- ta :: Ptr Float

  (ta ≣← 0) 0.0
  (ta ≣← 1) 0.0

  t ← etime_ ta

  putStrLn $ " user time:    " ++ show (ta ⥱ 0)
  putStrLn $ " system time:  " ++ show (ta ⥱ 1)
  putStrLn $ " process time: " ++ show t

  (ta ≣⊠) -- optional in this case
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top