Как я могу переписать или преобразовать этот код C ++ в код на Haskell - PullRequest
2 голосов
/ 19 января 2012

Код на C ++, который я хотел переписать или преобразовать:

class numberClass
{
    private:
    int value;
    public:
    int read()
    {
        return value;
    }
    void load(int x)
    {
        value = x;
    }
    void increment()
    {
        value= value +1;
    }
};

int main()
{
    numberClass num;
    num.load(5);
    int x=num.read();
    cout<<x<<endl;
    num.increment();
    x=num.read();
    cout<<x;
}

Я не знаю, как создать какой-либо объект (например, переменную в C ++), который может содержать значение в программе в haskell.

Пожалуйста, помогите.Спасибо

Ответы [ 3 ]

10 голосов
/ 19 января 2012

В принципе, вы не можете. Значения являются неизменяемыми, и в Haskell нет переменных в смысле блоков, в которых вы храните значения, такие как C ++ и подобные. Вы можете сделать нечто подобное, используя IORef s (это поля, в которых вы можете хранить значения), но использовать их почти всегда неправильно.

Haskell - это очень другой язык программирования, не стоит пытаться переводить код с языка, такого как C, C ++, Java или около того, на Haskell. Нужно смотреть на задачи с разных сторон и подходить к ним по-другому.

Как говорится:

module Main (main) where

import Data.IORef

main :: IO ()
main = do
    num <- newIORef 5 :: IO (IORef Int)
    x <- readIORef num
    print x
    modifyIORef num (+1)
    x <- readIORef num
    print x
8 голосов
/ 19 января 2012

Что ж, предполагая, что это перенос, а не изменчивость, вы можете легко иметь тип, который позволяет создавать только постоянные значения и приращения:

module Incr (Incr, incr, fromIncr, toIncr) where

newtype Incr a = Incr a deriving (Read, Show)

fromIncr :: Incr a -> a
fromIncr (Incr x) = x

incr :: (Enum a) => Incr a -> Incr a
incr (Incr x) = Incr (succ x)

toIncr :: a -> Incr a
toIncr = Incr

Как указал Даниэль, изменчивость исключена, но еще одной целью вашего класса является инкапсуляция, которую этот модуль обеспечивает так же, как класс C ++.Конечно, программисту на Haskell этот модуль может показаться не очень полезным, но, возможно, у вас есть примеры использования, когда вы хотите статически запретить пользователям библиотеки использовать регулярное сложение или умножение.

2 голосов
/ 22 января 2012

Прямой перевод вашего кода в haskell довольно глуп, но, конечно, возможен (как показано в ответе Даниэля).
Обычно, когда вы работаете с состоянием в haskell, вы можете работать с State Monad.Пока вы выполняете внутри Государственной Монады, вы можете запрашивать и обновлять свое состояние.Если вы хотите иметь возможность выполнять некоторые операции ввода-вывода в дополнение (как в вашем примере), вам нужно поместить свою монаду состояний поверх ввода-вывода.
При таком подходе ваш код может выглядеть следующим образом:

import Control.Monad.State
import Prelude hiding(read)

increment = modify (+1)
load = put
read = get

normal :: StateT Int IO ()
normal = do
    load 5
    x <- read
    lift (print x)
    increment
    x <- read
    lift (print x)

main = evalStateT normal 0

Но здесь у вас нет явного типа для вашего numberClass.Если вы хотите это, есть хорошая библиотека для взлома, которую вы можете использовать: data-lenses .
Используя линзы, код может быть немного ближе к вашей версии C ++:

{-# LANGUAGE TemplateHaskell #-}
import Control.Monad.State(StateT,evalStateT,lift)
import Prelude hiding(read)
import Data.Lens.Lazy((~=),access,(%=))
import Data.Lens.Template(makeLenses)

data Number = Number {
  _value :: Int
} deriving (Show)
$( makeLenses [''Number] )

increment = value %= succ
load x = value ~= x
read = access value

withLens :: StateT Number IO ()
withLens = do
    load 5
    x <- read
    lift $ print x
    increment
    x <- read
    lift $ print x

main = evalStateT withLens (Number 0)

Все еще не совсем твой код ... но хорошо, это haskell, а не еще один OO-язык.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...