簡體   English   中英

Haskell:將泛型類型轉換為泛型和INT

[英]Haskell : Generic type to generic and INT

我正在為大學項目開發​​Stack模塊。 它應該是通用“令牌”的列表,因此我使用了此構造函數:

module Stack (Stack(S), dup, swap, pop, size) where

import Prelude

data Stack a = S [a]

但是在大小操作上,im希望將列表的大小添加到其頭部,如下所示:

size[1,2,3,4] = [4,1,2,3,4]

但是我似乎無法定義此函數,因為在簽名中它會接收通用列表並返回通用列表,但實際上它會返回帶有INT的通用列表

size :: Stack a -> Stack a
size (S xs) = S(sizeAux xs)

sizeAux :: [a] -> [a]
sizeAux [] = [0]
sizeAux xs = length xs:xs

我嘗試過使用Show like

sizeAux :: [a] -> [a]
sizeAux [] = ["0"]
sizeAux xs = show((length xs)):xs

但是我得到了同樣的錯誤,只是這次是[Char]

有什么方法可以繞過它而無需將Stack構造函數更改為[String]之類的東西? 任何幫助將不勝感激。

例如,如果您嘗試以FORTH的方式構建堆棧計算機(如您的size說明所建議),則對堆棧使用[a]不太可能達到目的。

一種簡單直接的方法是首先確定您的計算機將要處理哪種原始數據類型,然后為每個單獨的類型創建帶有構造函數的數據類型,例如:

data Data = I Int | S String | Error String
    deriving Show -- for convenience only

然后,堆棧計算機的狀態將為[Data]類型-在這種情況下,它將使您可以對整數和字符串進行計算,並可以處理“帶外”錯誤。

然后,您的size運算符將如下所示:

size :: [Data] -> [Data]
size xs = I (length xs) : xs

我同意@shinobi的觀點,即使用ADT可能是最好的方法。 但是我只想讓您的意識成為一種性感的方法,那就是使用類型化的堆棧:

{-# LANGUAGE TypeOperators #-}

data Empty = Empty
data x :> xs = x :> xs
infixr 5 :>

class Stack a where sizeAux :: a -> Int
instance Stack Empty where sizeAux _ = 0
instance (Stack xs) => Stack (x :> xs) where 
    sizeAux (_ :> xs) = 1 + size xs

-- Here the head can be a different type from the rest of the stack,
-- and that is known statically.
size :: (Stack xs) => xs -> Int :> xs
size xs = sizeAux xs :> xs

dup :: x :> xs -> x :> x :> xs
dup (x :> xs) = x :> x :> xs

add :: Int :> Int :> xs -> Int :> xs
add (x :> y :> xs) = (x + y) :> xs

-- etc.

如果您確實要這樣做,可以這樣做:

import Data.List

size :: Num a => Stack a -> Stack a
size (S xs) = S (sizeAux xs)

sizeAux :: Num a => [a] -> [a]
sizeAux xs = genericLength xs : xs

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM