haskell编写在其中工作的构造函数

Eig*_*lue 1 constructor haskell data-structures

我有几个问题

我正在编写这个名为rope的构造函数,我喜欢这个

  data Rope = TextRope{ropeText :: String}
            | ConcatRope{rope1 :: Rope, rope2 :: Rope}
            | SubRope{subRopetext :: Rope, starting :: Integer, ending :: Integer}
            deriving Show
Run Code Online (Sandbox Code Playgroud)

首先,当我制作像这样的TextRope

*Main> let s =TextRope "why"
*Main> s
TextRope {ropeText = "why"}
*Main> 
Run Code Online (Sandbox Code Playgroud)

当我这样做时,想要获取构造函数的字符串,这就是为什么我并不确定.

对concat和sub构造函数也很好奇.具体来说,在我看来你正在调用这两个构造函数有事情发生,你正在返回将第1个绳索和第2个绳索连接在一起的结果,我不知道如何描述在这种语言中,你正在定义数据结构但不知何故返回的结果必须由结构计算

以下是这些功能如何工作的一些示例

> let tr = TextRope "Hello,"
> let sr = TextRope " world!"
> let hw = ConcatRope tr sr
> let ow = SubRope hw 4 4
> tr
Hello,
> sr
 world!
> hw
Hello, world!
Run Code Online (Sandbox Code Playgroud)

整体混淆,haskell构造函数和数据类型的新东西,所以一些指针会有所帮助(虽然不是c指针!)

bhe*_*ilr 5

数据构造函数永远不会工作.它们只保存您传递给它们的数据.如果你想完成工作,你应该定义所谓的智能构造函数,它们只是在将它传递给实际构造函数之前执行某些操作的函数.一个例子可能是

data Fraction = Fraction
    { numerator :: Int
    , denominator :: Int
    } deriving (Eq)

(%) :: Int -> Int -> Fraction
x % y =
    let (a, b) = reduce x y
    in Fraction a b

-- Reduces a fraction to it's simplest terms
reduce :: Int -> Int -> (Int, Int)
reduce num den = undefined
Run Code Online (Sandbox Code Playgroud)

在这里,您不会Fraction从模块中导出构造%函数,只是以最简化的形式构造一个的函数.

您遇到的另一个问题是您希望构造函数以不同方式打印出来.你可以通过不推导来实现这一目标Show.但是,我会警告Haskell约定show . read = read . show = id,这不符合你想做的事情.但这并不是一个严格的约定,并且没有什么能阻止你做以下事情:

data Rope = <your implementation minus the deriving Show bit>

instance Show Rope where
    show (TextRope t) = t
    show (ConcatRope r1 r2) = show r1 ++ show r2
    show (SubRope r starting ending) = <exercise left to reader>
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我建议不要使用具有不同字段名称的总和类型的记录,这可能会导致程序类型检查的问题,但是如果以不同的方式编写,则包含可在编译时捕获的错误.例如,如果你有代码会发生什么

> ropeText (ConcatRope (TextRope "Hello, ") (TextRope "world!"))
Run Code Online (Sandbox Code Playgroud)

这会导致错误并导致程序崩溃!相反,看起来你只想要一个Rope带有concatsubRope函数的类型,所以你可以非常简单地实现它

data Rope = Rope String deriving (Eq)

concatRope :: Rope -> Rope -> Rope
concatRope (Rope r1) (Rope r2) = Rope (r1 ++ r2)

-- Why use Integer instead of Int?  You might find it's easier to implement this function
subRope :: Rope -> Integer -> Integer -> Rope
subRope (Rope r) start end = Rope $ substr start end r
    where substr s e text = <exercise left to reader>
Run Code Online (Sandbox Code Playgroud)

现在绝对没有办法进行非法的绳索操作,唯一的区别是现在你必须用concatRope它代替ConcatRopesubRope代替SubRope.您可以保证这些功能可以满足您的需求,但是您没有一些无法帮助您的复杂类型.