Haskell ad-hoc多态性值,计算ad-hoc多态性列表的长度

时间:2018-11-15 12:57:56

标签: haskell functional-programming

我正在尝试从下面的代码中了解一种现象:

   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 一个创建列表,但是如果我想计算列表的长度,会出现错误吗?

1 个答案:

答案 0 :(得分:3)

在以下示例中,可能更容易理解此错误的含义:

roundTrip :: String -> String
roundTrip = show . read

因此,roundTrip readString,然后show将其放回(可能是相同的)String

但是read是一个多态函数:它以取决于输出类型的方式解析输入字符串。与解析Int相比,解析Bool是一个完全不同的要求!

详细制定者通过查看read的推断返回类型来决定要使用的read的具体实现。但是在表达式show . read中,中间类型可以是同时实现aShow的任何类型Read。编译器应该如何选择实现?

您可能会争辩说,在您的示例中这并不重要,因为length :: [a] -> Int统一对待其类型参数。无论您正在经历length [zer]的哪个实例,1始终是Bits。但是,这种情况通常对于编译器来说很难检测到,因此总是拒绝模棱两可的类型更简单,更可预测。

您可以通过提供具体的类型注释来解决此问题。

> length ([zer] :: [Bool])
1