我正在尝试从下面的代码中了解一种现象:
extended funcs: yes
xterm terminfo: xterm-old
bin directory: /ncurses-6.1/arm64//bin
lib directory: /ncurses-6.1/arm64//lib
include directory: /ncurses-6.1/arm64//include/ncurses
man directory: /ncurses-6.1/arm64//share/man
当我尝试这样做时:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Arrow
import Control.Monad
import Data.List
import qualified Data.Map as M
import Data.Function
import Data.Ratio
class (Show a, Eq a) => Bits a where
zer :: a
one :: a
instance Bits Int where
zer = 0
one = 1
instance Bits Bool where
zer = False
one = True
instance Bits Char where
zer = '0'
one = '1'
它工作正常,但是当我尝试时:
b = zer:[]
我收到此错误:
len = length b
有人可以向我解释为什么可以使用值 zer 和一个创建列表,但是如果我想计算列表的长度,会出现错误吗?
答案 0 :(得分:3)
在以下示例中,可能更容易理解此错误的含义:
roundTrip :: String -> String
roundTrip = show . read
因此,roundTrip
read
是String
,然后show
将其放回(可能是相同的)String
。
但是read
是一个多态函数:它以取决于输出类型的方式解析输入字符串。与解析Int
相比,解析Bool
是一个完全不同的要求!
详细制定者通过查看read
的推断返回类型来决定要使用的read
的具体实现。但是在表达式show . read
中,中间类型可以是同时实现a
和Show
的任何类型Read
。编译器应该如何选择实现?
您可能会争辩说,在您的示例中这并不重要,因为length :: [a] -> Int
统一对待其类型参数。无论您正在经历length [zer]
的哪个实例,1
始终是Bits
。但是,这种情况通常对于编译器来说很难检测到,因此总是拒绝模棱两可的类型更简单,更可预测。
您可以通过提供具体的类型注释来解决此问题。
> length ([zer] :: [Bool])
1