繁体   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