【问题标题】:How to go from a "polymorphic data-type a" to an instance of the Show class (without using "deriving Show")如何从“多态数据类型 a”到 Show 类的实例(不使用“派生 Show”)
【发布时间】:2012-11-18 01:57:52
【问题描述】:

在此文本下方,您可以看到一些用于创建 Arukone 谜题的代码。 但是有一个问题:多态数据类型Puzzle a 表示一个带有a 类型标签的Arukone 谜题。

但是我想要一个带有 Show 类实例的拼图类型(不使用 deriving Show。) show 功能就足够了,showsPrec 不是必需的。

那么你知道它是如何工作的吗?我想为所有类型 a 定义 Show,它们是以下 ToChar 类的实例?

class ToChar a where
 toChar :: a -> Char

instance ToChar Char where
 toChar = id

instance ToChar Int where
 toChar = head . show

代码:

import Data.Maybe (listToMaybe)

data Size  = Size Int Int deriving (Eq, Show)
data Pos   = Pos  Int Int deriving (Eq, Show)
data Link l = Link l Pos Pos
data Puzzle l = Puzzle Size [Link l]

assign :: Int -> a -> [a] -> [a]
assign 0 v (_:vs) = v:vs
assign n v (v’:vs) = v’: assign (n - 1) v vs

assign2 :: Int -> Int -> a -> [[a]] -> [[a]]
assign2 r c v vs = assign r (assign c v (vs !! r)) vs

assignPos :: Pos -> a -> [[a]] -> [[a]]
assignPos (Pos r c) = assign2 (r-1) (c-1)

tabulate :: Int -> (Int -> a) -> [a]
tabulate 0 _ = []
tabulate i f = f 0 : tabulate (i - 1) (f . (+1))

tabulate2 :: Int -> Int -> (Int -> Int -> a) -> [[a]]
tabulate2 b h f = tabulate h (\r -> tabulate b (\c -> f r c))

tabulatePos :: Size -> (Pos -> a) -> [[a]]
tabulatePos (Size h b) f = tabulate2 b h (\r c -> f (Pos (r +1) (c + 1)))

showPuzzle :: Puzzle a -> [[Maybe a]]
showPuzzle (Puzzle sz links) = tabulatePos sz findPosMaybe
  where findPosMaybe pos =  -- edit: findPosMaybe needs to be further left than the next line
          listToMaybe [l | Link l pos1 pos2 <- links, pos1 == pos || pos2 == pos]

解决方案和意见

*Main> show (Puzzle (Size 2 3) [Link 1 (Pos 1 1) (Pos 1 3), Link 2 (Pos 2 1) (Pos 2 3)])

"1 1\n2 2"


*Main> show (Puzzel (Size 5 5) [Link ’a’ (Pos 3 1) (Pos 4 3), Link ’b’ (Pos 5 1) (Pos 1 5), Link ’c’ (Pos 2 5) (Pos 5 5), Link ’d’ (Pos 4 1) (Pos 2 2)])

"    b\n d  c\na    \nd a  \nb   c"          <-- result -- remarks the spaces

上一个例子的putStrLn

    b
 d  c
a 
d a 
b   c

欢迎所有帮助。

【问题讨论】:

  • 请注意,我已经为showPuzzle 编辑了您的代码,以便它可以编译 - 续行需要进一步缩进。
  • 你能看看你的第二个例子吗? - 我认为你的意思是它与输出不同。

标签: haskell


【解决方案1】:

首先让我们使用ToChar 类将 Maybe 元素转换为空格或值:

maybeToString :: ToChar a => Maybe a -> String
maybeToString Nothing = " "
maybeToString (Just x) = toChar x : ""

现在我们可以制作 Show 实例了:

instance ToChar a => Show (Puzzle a) where
  show = unlines . map (concatMap maybeToString) . showPuzzle

我不清楚您是否想要填充,因此如果您想要更多空间,可以将您的 maybeToString 更改为 " "toChar x : " "

通过上面的定义,我们得到:

*Main> show (Puzzle (Size 2 3) [Link (1 :: Int) (Pos 1 1) (Pos 1 3), Link 2 (Pos 2 1) (Pos 2 3)]) 
"1 1\n2 2\n"
*Main> putStrLn $ show (Puzzle (Size 2 3) [Link (1 :: Int) (Pos 1 1) (Pos 1 3), Link 2 (Pos 2 1) (Pos 2 3)]) 
1 1
2 2

示例 2:

*Main> show (Puzzle (Size 5 5) [Link 'a' (Pos 3 1) (Pos 4 3), Link 'b' (Pos 5 1) (Pos 1 5), Link 'c' (Pos 2 5) (Pos 5 5), Link 'd' (Pos 4 1) (Pos 2 2)])
"    b\n d  c\na    \nd a  \nb   c\n"
*Main> putStr it
    b
 d  c
a    
d a  
b   c

【讨论】:

  • 嘿,谢谢,小问题,我看到我在第二个例子中犯了一个错误。并改变了这一点。你也能解决这个问题吗?所以链接 1 也是链接 'a' ?
  • @DieterVerbeemen 是的 - 请参阅编辑 - 这根据您上面的示例工作。这是你想要的吗?
  • @DerpDerpington 你好。你不接受我的回答:你有什么想要改变的吗?
  • 答案很完美,但正在测试删除问题,抱歉:)
猜你喜欢
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 2020-08-03
  • 1970-01-01
相关资源
最近更新 更多