Cross-posted at Code Review SEHaskell: Пространственно Типы и IO
В своих попытках ухватить экзистенциальные типы в Haskell я решил реализовать фиксированной длины типа вектор данных основанную на целых числах. Я использую ghc 7.8.3.
В частности, я хотел написать программу, которая запрашивает у пользователя возможное новое значение для добавления к вектору фиксированной длины, а затем отображает результирующий вектор.
Сначала я написал первую версию программы, как это:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE Rank2Types #-}
import System.IO (hFlush, stdout)
data Z
data S n
data Vect n where
ZV :: Vect Z
CV :: Int -> Vect n -> Vect (S n)
data AnyVect = forall n. AnyVect (Vect n)
instance Show (Vect n) where
show ZV = "Nil"
show (CV x v) = show x ++ " : " ++ show v
vecAppend :: Int -> Vect n -> Vect (S n)
vecAppend x ZV = CV x ZV
vecAppend x v = CV x v
appendElem :: AnyVect -> IO AnyVect
appendElem (AnyVect v) = do
putStr "> "
hFlush stdout
x <- readLn
return $ if x == 0 then AnyVect v else AnyVect $ vecAppend x v
main = do
AnyVect v <- appendElem $ AnyVect ZV
putStrLn $ show v
, который работает, как ожидалось. Тогда я решил избавиться от ненужного AnyVect:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE Rank2Types #-}
import System.IO (hFlush, stdout)
data Z
data S n
data Vect n where
ZV :: Vect Z
CV :: Int -> Vect n -> Vect (S n)
instance Show (Vect n) where
show ZV = "Nil"
show (CV x v) = show x ++ " : " ++ show v
vecAppend :: Int -> Vect n -> Vect (S n)
vecAppend x ZV = CV x ZV
vecAppend x v = CV x v
appendElem :: Vect n -> (forall n. Vect n -> a) -> IO a
appendElem v f = do
putStr "> "
hFlush stdout
x <- readLn
return $ if x == 0 then f v else f $ vecAppend x v
main = do
appendElem ZV show >>= putStrLn
, который работает, а я даже не очень нравится, как основной написано.
Есть ли какой-нибудь другой более простой/чистый способ его написать?
Похоже, это было бы лучше для codereview? –
Перекресток, отправленный в codereview (который я не знал, что он существует). Благодарю. –
'vecAppend = CV' является более прямым. Я бы также переименовал его как 'vecCons', так как« append »звучит так, как если бы он работал на двух векторах. – chi