为什么我不能将String用作类型类?

iwe*_*ein 2 haskell

这是一个绝对的初学者Haskell问题.可能需要进行一些编辑.

给出以下代码:

import Data.Maybe
someFunction :: String b => Int -> Maybe b
someFunction x = Nothing
Run Code Online (Sandbox Code Playgroud)

我收到错误:

Main.hs@2:18-2:26`String' is applied to too many type arguments
In the type signature for `someFunction':
  someFunction :: String b => Int -> Maybe b
Run Code Online (Sandbox Code Playgroud)

我想明白为什么我看到这个错误.

类似的签名适用于:

import Data.Maybe
somethingElse :: Num b => Int -> Maybe b
somethingElse x = Nothing
Run Code Online (Sandbox Code Playgroud)

Num和String之间的区别是什么?(可能是因为String不是类型类?)

我能否以与Num类似的方式为String创建速记?(可能是?)

如果我遇到这种情况,如何找到正确的类型?

更新:

为了说明我想要为String类型提供简写的原因:

somethingElse ::  String -> String -> String -> String
somethingElse x s t  =  t ++ s ++ x
Run Code Online (Sandbox Code Playgroud)

编译,但我更愿意写:

somethingElse :: ??? a => a -> a -> a -> a
somethingElse x s t  =  t ++ s ++ x
Run Code Online (Sandbox Code Playgroud)

pyo*_*yon 5

更新的答案:

在阅读了对@YellPika的回答的评论之后,抓住我之前所说的话.如果要为其定义较短类型的同义词String,您只需要做的就是

-- Not that this serves any useful purpose.
type Str = String
Run Code Online (Sandbox Code Playgroud)

然后,您可以在类型注释中使用同义词:

someFunction :: Int -> Maybe Str
someFunction x = Nothing
Run Code Online (Sandbox Code Playgroud)

但是,实际上,这是一个坏主意.每个人都知道这String代表[Char],因为它在标准库中.只有你知道你的同义词Str代表String.如果您关心长类型注释,可以使用Haskell的类型推断.

Num类型类,而不是类型.甲型类定义的其被提供用于多种类型的方法的集合在ad-hoc方式.主流语言中最接近的类比是C++标准库和原始STL中的概念概念.(但是,类型类是Haskell语言的本机结构,而C++/STL概念只存在于C++程序员的头脑中.)


我之前说过的话:

(留在这里仅供参考)

您可能正在寻找-XOverloadedStrings扩展名.这使得字符串文字具有类型IsString s => s.

以下是ghci会话的示例:

> :set -XOverloadedStrings
> import Data.String
> import Data.ByteString
> import Data.Text
> :t "a"
"a" :: IsString a => a
> :i IsString
class IsString a where
  fromString :: String -> a
    -- Defined in `Data.String'
instance IsString ByteString
  -- Defined in `Data.ByteString.Internal'
instance IsString Text -- Defined in `Data.Text'
instance IsString [Char] -- Defined in `Data.String'
Run Code Online (Sandbox Code Playgroud)

在Haskell源文件(*.hs)中,您可以通过在顶部添加来使用此扩展:

{-# LANGUAGE OverloadedStrings #-}
module What.Ever where

-- ...
Run Code Online (Sandbox Code Playgroud)

注意:所有这些都假设您使用的是GHC.我还没有尝试过其他Haskell实现.

  • @iwein:Haskell没有类型的继承概念."类型空间"是平的.但是,类型类可以是分层相关的. (2认同)

Yel*_*ika 5

这个错误有点误导.String(定义为type String = [Char])没有类型参数,但是你给它一个(String b).

但是,只能在约束中指定类型类(即在之前=>),因此无论您给出多少参数,您尝试的都将无法编译String.

我想(你想)做的只是简单someFunction :: Int -> Maybe String.


好吧,如果你想要一个速记,那么我想你可以这样做:

type S = String

someFunction :: Int -> Maybe S
Run Code Online (Sandbox Code Playgroud)

虽然我认为这会混淆代码.

作为旁注:类型类不是为类型创建本地定义的缩写.


加成:

我记得你可以使用类型相等约束来模拟shorthands.

{-# LANGUAGE TypeFamilies #-} -- Or GADTs

somethingElse :: s ~ String => s -> s -> s -> s
somethingElse x y z = x ++ y ++ z
Run Code Online (Sandbox Code Playgroud)

通过使用类型等式,"同义词"现在在本地定义,因此比定义更难以阅读type SomeOtherNameForStringThatIsShorterThan'String' = String.

但我仍然建议只写出完整的类型.